mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
Compare commits
254 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
dd71a004e2 | ||
|
45091fbd72 | ||
|
988d5aebfa | ||
|
8c3671fae6 | ||
|
2a12af481a | ||
|
7817e64695 | ||
|
ebbaa39098 | ||
|
d3dcbbd4f2 | ||
|
3045995bbc | ||
|
1b4233d6ad | ||
|
34aa8fe8b4 | ||
|
baa97e9ff1 | ||
|
03afc4a353 | ||
|
ef4ebeb7ee | ||
|
80d8851e62 | ||
|
ead135f716 | ||
|
49dc61a92c | ||
|
af0309cc40 | ||
|
4ed7421b1c | ||
|
3058354dba | ||
|
20a8c5d240 | ||
|
0749a34342 | ||
|
e595eed57d | ||
|
a7576f0b6c | ||
|
657e5dda5d | ||
|
8fb6a2b24b | ||
|
53cac302d8 | ||
|
2c6c014dd8 | ||
|
a7071f580e | ||
|
de5327a048 | ||
|
7ab94c7bcb | ||
|
0f80fc5e86 | ||
|
d169f30e5c | ||
|
7a1842cba6 | ||
|
e4e9d7a55f | ||
|
ccbef6ce6c | ||
|
7461a1ba3a | ||
|
bb55e3036e | ||
|
bbf2cca198 | ||
|
8ce034d124 | ||
|
4030698007 | ||
|
66fea5c9f1 | ||
|
285574eeaa | ||
|
55cfb057e0 | ||
|
b4c538cff7 | ||
|
5a626fef9f | ||
|
2bcd8ba8f3 | ||
|
2dacc776bd | ||
|
a91d687a1a | ||
|
0d3882d43e | ||
|
72ad601328 | ||
|
2c6fd804f6 | ||
|
c590444b7d | ||
|
4805af7915 | ||
|
171b20a80d | ||
|
d00ae923ab | ||
|
d8ab5dc5c6 | ||
|
292af5d4f4 | ||
|
3d6b31b115 | ||
|
9e523073aa | ||
|
32d8e473fb | ||
|
5cd25df60c | ||
|
52c4816c9c | ||
|
6f6b05ffcb | ||
|
6dd5854b7a | ||
|
83425df0b6 | ||
|
82b09eaa8e | ||
|
ec5b1aadab | ||
|
f786510ba2 | ||
|
f006884e57 | ||
|
c0a005b3cd | ||
|
0c91893643 | ||
|
796da9e0f6 | ||
|
5d539be071 | ||
|
1df138d876 | ||
|
71b0140003 | ||
|
a33adf365d | ||
|
8d82b05071 | ||
|
930e3b4200 | ||
|
2543f2c486 | ||
|
d919817c35 | ||
|
6bbb596968 | ||
|
8aec1974bb | ||
|
b3ad9ec699 | ||
|
87410442b6 | ||
|
305735a886 | ||
|
41b7e1546a | ||
|
f3972e4795 | ||
|
e7ea087a6e | ||
|
749ba57dcc | ||
|
0360b0d0e7 | ||
|
2b495e0f87 | ||
|
32b11e1a53 | ||
|
db81c07b27 | ||
|
1c2401eb6c | ||
|
5828d347f7 | ||
|
9c64622718 | ||
|
f9260d0141 | ||
|
746cdaff01 | ||
|
179d5b87fc | ||
|
51dca45a0c | ||
|
62ad9b41dd | ||
|
8b87a6968a | ||
|
faf562fd4e | ||
|
6a09a2fbd6 | ||
|
bc32ffe2f9 | ||
|
ff16bbd777 | ||
|
f7f8a6b131 | ||
|
a3310e2954 | ||
|
0b08666310 | ||
|
42db3fbee0 | ||
|
bfa25d6276 | ||
|
824c495d33 | ||
|
561be36958 | ||
|
8bd0437497 | ||
|
18c9cef1ea | ||
|
2c66d57d4b | ||
|
29200d040e | ||
|
385738cadd | ||
|
a2591d6e98 | ||
|
fe97a38e77 | ||
|
552f5fc4e7 | ||
|
21d3d489fd | ||
|
78b7e4e252 | ||
|
5d984b606e | ||
|
88b1e30494 | ||
|
939071bf25 | ||
|
655682b5d2 | ||
|
b1418b6bcd | ||
|
35c8b3d22c | ||
|
e5ae02e3fa | ||
|
f0da21ea13 | ||
|
eb35faaf7d | ||
|
05f03d6e38 | ||
|
0d4284df29 | ||
|
cade92cda1 | ||
|
f0bbf64da0 | ||
|
6458f8b581 | ||
|
1770a18598 | ||
|
5f136032a2 | ||
|
63efcf3927 | ||
|
468dc1115e | ||
|
d53e0fd5c3 | ||
|
14b907b01c | ||
|
e0d87da768 | ||
|
42b584e38d | ||
|
a0f79bdd5f | ||
|
4372d55dd1 | ||
|
13672280b6 | ||
|
5b134cb23e | ||
|
87cf0b7a3d | ||
|
8b14723e9e | ||
|
7fe59548cd | ||
|
15f13ac936 | ||
|
5b176f97a4 | ||
|
0bb6f87776 | ||
|
c06d2389e9 | ||
|
548a33c728 | ||
|
4336b55f4e | ||
|
c12c7378e9 | ||
|
a299d8d348 | ||
|
c7bf474a42 | ||
|
8d65cc6dc0 | ||
|
f2b9f0e8dd | ||
|
30f05ba714 | ||
|
76445411a5 | ||
|
4425918d31 | ||
|
6888ea68b6 | ||
|
abb82a2396 | ||
|
6192ca81d9 | ||
|
d06c5efa54 | ||
|
f859b8d2ae | ||
|
035d5fd5b9 | ||
|
93d578d9b8 | ||
|
d756628297 | ||
|
a4cde807bc | ||
|
83c9677899 | ||
|
b14ed38a48 | ||
|
2bf0967a47 | ||
|
7ed306d127 | ||
|
5a029eb29f | ||
|
230adc8235 | ||
|
982a9a5157 | ||
|
c8e4921a0a | ||
|
786245efe5 | ||
|
74460f22bf | ||
|
a843d03af1 | ||
|
d3f3e856e4 | ||
|
be3c6048ed | ||
|
2a0222226a | ||
|
50c3951017 | ||
|
ea1ad945b4 | ||
|
8cde8464eb | ||
|
14b108f104 | ||
|
330dbce1e7 | ||
|
adeb6314fb | ||
|
78a09b5926 | ||
|
d05765c670 | ||
|
a5a4b72d1c | ||
|
955b1c914f | ||
|
5b28aa7e02 | ||
|
f34a6d66a0 | ||
|
104bddc560 | ||
|
e7107b789e | ||
|
f2e71eb668 | ||
|
f275346ecc | ||
|
33b47142e4 | ||
|
5f3d42bcd8 | ||
|
3f2dd916c1 | ||
|
0d50ec57f5 | ||
|
7301f2de08 | ||
|
8c7d387e86 | ||
|
6c5a448dec | ||
|
a84f9a8e19 | ||
|
545613e0e7 | ||
|
ac4da6e380 | ||
|
4d5cbaf57d | ||
|
a4a2466bf4 | ||
|
a0cdfc432a | ||
|
60c858689b | ||
|
9686a9b474 | ||
|
0f6265a97f | ||
|
7b1c097958 | ||
|
58e21d8e37 | ||
|
e1f04cd6fa | ||
|
7775698bac | ||
|
8f52603665 | ||
|
c40fb4b4aa | ||
|
161fa8ead4 | ||
|
115eb9fdb4 | ||
|
b7112ece6c | ||
|
f7c8f582ea | ||
|
ada85b693e | ||
|
a1a8c5d94c | ||
|
505bcee926 | ||
|
c02c081d91 | ||
|
c8566fab77 | ||
|
54c4e69299 | ||
|
31b87544f1 | ||
|
cd3cda2654 | ||
|
c98fdd9120 | ||
|
10ffd08c82 | ||
|
4a199fe4ac | ||
|
98fa6206ac | ||
|
ce23ba64bd | ||
|
02c668a6a9 | ||
|
9de337d2ee | ||
|
fa8c7c35b5 | ||
|
3d13eb002f | ||
|
b2fb654bb3 | ||
|
cd834c79ba | ||
|
65aafacd8e | ||
|
ebd92dcd31 | ||
|
0003d6391c |
138
CONTRIBUTORS
138
CONTRIBUTORS
@ -2189,7 +2189,7 @@ Harald Milz <hm@seneca.muc.de>
|
||||
for his CUTR patch, which was used as a base to implement the SVDRP command EDIT
|
||||
for reporting a bug in parsing the '-l' command line option
|
||||
|
||||
Marko Mäkelä <marko.makela@hut.fi>
|
||||
Marko Mäkelä <marko.makela@iki.fi>
|
||||
for making repeat keys be ignored when waiting for a keypress to cancel an operation
|
||||
for reporting that a menu was automatically closed when a replay ends
|
||||
for suggesting to ignore k_Repeat when deciding whether the same key has been
|
||||
@ -2200,6 +2200,18 @@ Marko M
|
||||
for suggesting to simplify some conditional expressions in skinlcars.c and skinsttng.c
|
||||
for reporting some uninitialized item area coordinates in cSkinLCARSDisplayMenu
|
||||
for reporting a problem with the video directory not being set correctly with --edit
|
||||
for reporting a compiler warning about the use of strncpy() in strreplace()
|
||||
for adding support for kernel based LIRC driver
|
||||
for reporting a possible heap-use-after-free in cDvbTuner::Action()
|
||||
for reporting a flaw in initializing cDvbPlayerControl and cTransferControl
|
||||
for reporting a possible call to poll() in cSectionHandler::Action() without any
|
||||
filters
|
||||
for avoiding the memcpy() call in cGlyph::cGlyph() if the bitmap is empty
|
||||
for avoiding unnecessary processing in cDvbSubtitleConverter::FinishPage() if there
|
||||
are no areas
|
||||
for avoiding a zero sized array in cDevice::GetDevice()
|
||||
for reporting a crash when deleting a recording that is currently being edited, and
|
||||
then immediately deleting the edited version, too
|
||||
|
||||
Patrick Rother <krd-vdr@gulu.net>
|
||||
for reporting a bug in defining timers that only differ in the day of week
|
||||
@ -2343,6 +2355,7 @@ Andr
|
||||
for reporting a bug in selecting the last replayed recording in the Recordings menu
|
||||
in case there are folders and plain recordings with names that differ only in
|
||||
non-alphanumeric characters
|
||||
for reporting a problem with permanently looping through PMT PIDs on a SatIP receiver
|
||||
|
||||
Jürgen Schilling <juergen_schilling@web.de>
|
||||
for reporting that color buttons were displayed in the recording info menu if it
|
||||
@ -2448,6 +2461,19 @@ Christoph Haubrich <christoph1.haubrich@arcor.de>
|
||||
for implementing anti-aliasing for cPixmap::DrawSlope() and cPixmap::DrawEllipse()
|
||||
for reporting an unnecessary double call to Display() in cMenuRecording::RefreshRecording()
|
||||
for reporting too much memory being allocated in the cImage constructors
|
||||
for making the 'Edit path' dialog also show the total size of all recordings in that path
|
||||
for suggesting to make cRecordingInfo::Errors() return -1 for old recordings, and
|
||||
reporting a missing 'const'
|
||||
for reporting that the edited recording is not deleted in case of an error
|
||||
for reporting missing '0x09=H.265 video, 0x19 = AC4 audio' in vdr.5
|
||||
for reporting a problem with the call to EpgHandlers.EndSegmentTransfer()
|
||||
for fixing handling zero bytes in cH264Parser
|
||||
for implementing parsing frame rate and image size for MPEG2, H.264 and H.265
|
||||
for reporting a bug in generating the index file in the cutter
|
||||
for adding the frame width, height, scan type and aspect ratio of a recording to the 'F'
|
||||
tag of the 'info' file
|
||||
for adding a workaround in detecting frame height for channels with wrong crop parameters
|
||||
for reporting duplicate component entries in the info of an ongoing recording
|
||||
|
||||
Pekka Mauno <pekka.mauno@iki.fi>
|
||||
for fixing cSchedule::GetFollowingEvent() in case there is currently no present
|
||||
@ -2527,6 +2553,49 @@ Markus Ehrnsperger <markus.ehrnsperger@googlemail.com>
|
||||
for reporting a problem with missing 'INCLUDES += -I$(DVBDIR)/include' in an existing
|
||||
Make.config
|
||||
for reporting a bug in error handling when loading a plugin
|
||||
for reporting a possible crash in cIndexFile::GetClosestIFrame()
|
||||
for reporting a missing 'const' in cTimers::GetTimerForEvent()
|
||||
for suggesting to add a chapter about locking to PLUGINS.html
|
||||
for fixing unnecessary interruption of ongoing recordings if timers avoided the
|
||||
transfer mode receiver device
|
||||
for reporting broken video data streams on systems without output device when switching
|
||||
live channel to a different transponder while recording
|
||||
for fixing a possible crash in cDevice::StopSectionHandler()
|
||||
for making using a dummy OSD if no OSD provider is available not be considered an error
|
||||
any more
|
||||
for removing syslog calls in child process after fork()
|
||||
for adding the move constructor to cString for better performance
|
||||
for fixing handling primary device on headless systems
|
||||
for adding a 15 second grace period before actually stopping a VPS timer
|
||||
for making the primary device no longer start unnecessary threads if it doesn't have
|
||||
a decoder
|
||||
for improving handling present/following data for VPS timers
|
||||
for making logging event status changes also show the previous status
|
||||
for making a device always being kept occupied if a timer is in VPS margin or needs the
|
||||
transponder
|
||||
for suggesting to enable unused devices to be put into a power save mode
|
||||
for a patch that was used to implement power save mode for cDvbDevice
|
||||
for suggesting to add 'lnbPowerTurnedOn = false' to cDvbTuner::ProvidesFrontend()
|
||||
for reporting a crash in strreplace() for multiple replacements with strings of
|
||||
different lengths
|
||||
for suggesting to add the lines from 'Fixed a timeout in cDvbDevice while tuning after
|
||||
the frontend has been reopened' to cDvbTuner::ProvidesFrontend()
|
||||
for improving the error message when closing a frontend
|
||||
for reporting a problem in cSchedule::Sort(), in case hasRunning was true, but there
|
||||
was no event with RunningStatus() >= SI::RunningStatusPausing
|
||||
for reporting problem with duplicate events if they are moved to a lower table ID and
|
||||
at the same time get a new event ID
|
||||
for reporting a bug in handling negative values in cSource::Position() on
|
||||
systems where 'int' is 64 bit
|
||||
for suggesting a fix for expiring of one-time VPS timers in case there is more than
|
||||
one event with the same VPS time
|
||||
for fixing handling margins for timers that are not VPS controlled and not spawned
|
||||
for implementing cStatus::OsdItem2() with the information whether the item is selectable
|
||||
for reporting an improper call of cStatus::OsdCurrentItem() before cStatus::OsdItem2()
|
||||
for fixing unnecessary calls to DisplayCurrent() for editable menu items
|
||||
for implementing cStatus::OsdCurrentItem2() with the index of the current item
|
||||
for adding missing calls to cStatus::MsgOsdStatusMessage() and implementing
|
||||
cStatus::OsdStatusMessage2() with the type of the message
|
||||
|
||||
Werner Färber <w.faerber@gmx.de>
|
||||
for reporting a bug in handling the cPluginManager::Active() result when pressing
|
||||
@ -2652,6 +2721,7 @@ J
|
||||
for suggesting to no longer log unaligned marks in cMarks::Align()
|
||||
for reporting some warnings from g++ 7.2.0 regarding fixed buffer sizes in
|
||||
cMenuEditTimeItem::Set() and cCountdown::Update()
|
||||
for fixing symmetry of Begin/EndSegmentTransfer() calls in cEIT::cEIT()
|
||||
|
||||
Peter Pinnau <vdr@unterbrecher.de>
|
||||
for reporting that 'uint32_t' requires including stdint.h in font.h on some systems
|
||||
@ -2758,7 +2828,7 @@ Benjamin Hess <benjamin.h@gmx.ch>
|
||||
for enhancing the SVDRP command CLRE to allow clearing the EPG data of a particular
|
||||
channel
|
||||
|
||||
Winfried Köhler <w_koehl@gmx.de>
|
||||
Winfried Köhler <nvdec@quantentunnel.de>
|
||||
for fixing finding new transponders
|
||||
for fixing wrong value for TableIdBAT in libsi/si.h
|
||||
for reporting a compiler warning in calculations involving FramesPerSecond()
|
||||
@ -2777,6 +2847,19 @@ Winfried K
|
||||
for improving handling missing VDRPluginDestroyer()
|
||||
for fixing a compiler warning
|
||||
for fixing handling $(PKG_CONFIG) in newplugin
|
||||
for using __cplusplus instead of DISABLE_TEMPLATES_COLLIDING_WITH_STL, and using
|
||||
std::min(), std::max() and std::swap() is available
|
||||
for adding some missing "AUTO" values to vdr.5
|
||||
for fixing default values for DVB-T
|
||||
for adding missing rounding when dividing frequencies in processing the NIT
|
||||
for suggesting to add note about not messing with event ids in EPG handlers
|
||||
for adding a missing initialization of cChannel::nameSourceMode
|
||||
for suggesting to make APIVERSION a simple number, independent from VDRVERSION
|
||||
for reporting a compiler warning with gcc 14.1.0
|
||||
for suggesting to remove defining DEPRECATED_* macros with value 0, because this
|
||||
is the preprocessor's default
|
||||
for suggesting a fix for handling negative values in cSource::Position() on
|
||||
systems where 'int' is 64 bit
|
||||
|
||||
Hans-Werner Hilse <hilse@web.de>
|
||||
for adding the command line option --userdump to enable core dumps in case VDR
|
||||
@ -2879,6 +2962,7 @@ Johann Friedrichs <johann.friedrichs@web.de>
|
||||
want the actual response strings
|
||||
for reporting a bug in handling the tfRecording flag in the SVDRP commands MODT and UPDT
|
||||
for adding a missing '-D' to the 'plugins' target of the Makefile
|
||||
for adding code for the 'qks' audio track
|
||||
|
||||
Timo Helkio <timolavi@mbnet.fi>
|
||||
for reporting a hangup when replaying a TS recording with subtitles activated
|
||||
@ -2946,6 +3030,7 @@ Manuel Reimer <Manuel.Reimer@gmx.de>
|
||||
number is given
|
||||
for reporting that LSTE doesn't work after PUTE in case a channel didn't already
|
||||
have EPG data
|
||||
for suggesting to make APIVERSION a simple number, independent from VDRVERSION
|
||||
|
||||
Rene van den Braken <rene@vandenbraken.name>
|
||||
for reporting a bug in writing the PCR pid into the PMT in
|
||||
@ -2999,6 +3084,7 @@ Lars Hanisch <dvb@flensrocker.de>
|
||||
for fixing a typo in the description of cTimers::GetTimersRead()
|
||||
for suggesting to use dynamic buffering in handling CA descriptors to avoid a
|
||||
possible buffer overflow
|
||||
for suggesting to make APIVERSION a simple number, independent from VDRVERSION
|
||||
|
||||
Alex Lasnier <alex@fepg.org>
|
||||
for adding tuning support for ATSC devices
|
||||
@ -3288,6 +3374,16 @@ Mike Hay <mike.hay@linenshorts.com>
|
||||
Stefan Hofmann <stefan.hofmann@t-online.de>
|
||||
for suggesting to implement support for remote controls that only have a combined
|
||||
"Play/Pause" key instead of separate keys for "Play" and "Pause"
|
||||
for a fix for compilers that don't like non-constant format strings
|
||||
for suggesting to implement jumping between errors while replaying a recording
|
||||
for adding vdrrootdir and incdir to vdr.pc
|
||||
for fixing some typos in the translation files
|
||||
for adding 1 to Utf8BufSize() for worst case
|
||||
for adding a header to the backtrace
|
||||
for adding parameter checks to strn0cpy()
|
||||
for making the info files of recordings only be re-read if they have been modified
|
||||
for reporting missing setting the file name of the info file after renaming a recording
|
||||
for adding '~' to the list of delimiters in cTextWrapper
|
||||
|
||||
Stefan Blochberger <Stefan.Blochberger@gmx.de>
|
||||
for suggesting to automatically display the progress display whenever replay of a
|
||||
@ -3350,6 +3446,14 @@ Matthias Senzel <matthias.senzel@t-online.de>
|
||||
for reporting a high CPU load during replay with active progress display
|
||||
for reporting that the lock on the Channels list in cDisplayChannel was still held
|
||||
when Flush() was called
|
||||
for reporting that if an error occurs while recording, the respective entry in the list
|
||||
of recordings was not updated immediately
|
||||
for fixing restoring the volume at program start
|
||||
for fixing height calculation in progress display
|
||||
for fixing an unnecessary double display of the current menu item in page up/down
|
||||
for fixing an unnecessary double display of menu items in the Recordings menu
|
||||
for reporting a bug in handling cSkinDisplayMenu::GetTextAreaFont()
|
||||
for reporting characters being cut off while editing in the LCARS skin
|
||||
|
||||
Marek Nazarko <mnazarko@gmail.com>
|
||||
for translating OSD texts to the Polish language
|
||||
@ -3501,6 +3605,8 @@ Claus Muus <email@clausmuus.de>
|
||||
".../Volume linearize"
|
||||
for reporting multiple recording entries in case a recording is started during the
|
||||
initial reading of the video directory
|
||||
for reporting that getting the lock for removing deleted recordings may fail if the
|
||||
disk is full
|
||||
|
||||
Dieter Ferdinand <dieter.ferdinand@gmx.de>
|
||||
for reporting a problem with jumping to an absolute position via the Red key in
|
||||
@ -3541,6 +3647,11 @@ Stefan Herdler <herdler@gmx.de>
|
||||
".sort" file
|
||||
for reporting faulty memory handling in cString::Append()
|
||||
for adding failsafe defaults for 'make LCLBLD=1' to the Makefile
|
||||
for reporting the index file of a recording not being regenerated in case it is
|
||||
present, but empty
|
||||
for reporting a missing check for self-assignment in the move assignment operator
|
||||
for modifying handling channel names with source to make it thread safe
|
||||
for fixing setting T2 system ID from NIT
|
||||
|
||||
Tobias Faust <tobias.faust@gmx.de>
|
||||
for the original "jumpingseconds" patch
|
||||
@ -3602,6 +3713,8 @@ Onur Sent
|
||||
for fixing handling shared CA pids
|
||||
for fixing handling the S2SatelliteDeliverySystemDescriptor for transponders broadcasting
|
||||
in "backwards compatibility mode" according to ETSI EN 300 468
|
||||
for pointing out some potentially mistakable code in cSectionHandler::SetStatus()
|
||||
for adding periodic calls to malloc_trim(0) to reduce memory consumption
|
||||
|
||||
Helmut Binder <cco@aon.at>
|
||||
for improving calculating signal strength and quality
|
||||
@ -3652,6 +3765,13 @@ Helmut Binder <cco@aon.at>
|
||||
for reporting a problem with PMT handling in case locking the Channels list times out
|
||||
for avoiding a lengthy lock on the Channels list when starting a recording
|
||||
for preventing switching devices for pattern timers
|
||||
for pointing out that cChannel::Transponder(void) is called very often
|
||||
for fixing flushing old data from the section handler
|
||||
for removing unused declaration of cDvbTuner::SetFrontendType()
|
||||
for fixing handling incomplete multi-packet CAT
|
||||
for fixing a memory leak in handling the NIT
|
||||
for reporting a possible memory leak in creating fonts
|
||||
for fixing a possible deadlock in cDevice::DetachAllReceivers()
|
||||
|
||||
Ulrich Eckhardt <uli@uli-eckhardt.de>
|
||||
for reporting a problem with shutdown after user inactivity in case a plugin is
|
||||
@ -3672,6 +3792,8 @@ J
|
||||
use VPS and fully overlaps a second event that is longer than the original one
|
||||
for reporting a missing EPISODE macro expansion in case the event doesn't yet have a
|
||||
short text when generating the pattern timer file name
|
||||
for reporting a problem with spawned timers jumping to the next event in case
|
||||
Setup.EPGLinger is very small
|
||||
|
||||
Stefan Verse <Verse@amotronics.de>
|
||||
for fixing an occasional black screen when switching channels
|
||||
@ -3684,3 +3806,15 @@ Bernd Kuhls <bernd.kuhls@t-online.de>
|
||||
|
||||
Ulf Grüne <ulf.gruene@t-online.de>
|
||||
for reporting the need for more than 15 modulation systems in cDevice::GetDevice()
|
||||
|
||||
Timo Weingärtner <timo@tiwe.de>
|
||||
for reporting an integer overflow in calculating the disk use percentage if there's
|
||||
more than 20TB of recordings
|
||||
|
||||
Jose Angel <joseangelpp@gmail.com>
|
||||
for reporting a bug in default values for DVB-T
|
||||
|
||||
Andreas Baierl <post@andreasbaierl.de>
|
||||
for implementing scaling images
|
||||
for reporting a problem in the progress display when switching from "pause" to
|
||||
"slow back"
|
||||
|
449
HISTORY
449
HISTORY
@ -9640,3 +9640,452 @@ Video Disk Recorder Revision History
|
||||
by Jürgen Schneider).
|
||||
- No longer switching devices for pattern timers (thanks to Helmut Binder).
|
||||
- cTimer::TriggerRespawn() now only acts on local timers.
|
||||
|
||||
2021-04-20: Version 2.5.3
|
||||
|
||||
- When spawning pattern timers, the new function cTimers::GetTimerForEvent() is now used
|
||||
to check whether a matching event already has a local spawned timer. Reason: creating a timer
|
||||
from the Schedule menu (by pressing the Red button), then pressing Red again to edit
|
||||
the timer, making it a pattern timer and moving it to a remote machine, did not cause
|
||||
an immediate respawn on the remote machine, because at that time the event on the remote
|
||||
machine was still covered by the initial timer (which, from the remote machine's standpoint,
|
||||
was "remote").
|
||||
- Now adjusting spawned timers before setting events to timers.
|
||||
- Fixed dropping outdated events.
|
||||
- To avoid problems with very short events, non-VPS pattern timers now spawn timers for all
|
||||
matching events that would start while the first one is still recording.
|
||||
- Now making sure that spawned timers with reduced start/stop margins actually record with
|
||||
the full margins.
|
||||
- Fixed the timer indicator in the Schedule menu in case an event is already over, but the
|
||||
timer is still recording.
|
||||
- The new functions cTimer::Start/StopTimeEvent() are now used in the LCARS skin to display
|
||||
the start/stop times of timers in the main menu.
|
||||
- EXPIRELATENCY now only applies to VPS timers.
|
||||
- Deleting expired timers is now triggered immediately after the timers are modified.
|
||||
|
||||
2021-05-21: Version 2.5.4
|
||||
|
||||
- Now using a separate fixed value for internal EPG linger time. This fixes problems with
|
||||
spawned timers jumping to the next event in case Setup.EPGLinger is very small. (reported
|
||||
by Jürgen Schneider).
|
||||
- Fixed a possible crash in the Schedule menu, in case Setup.EPGLinger is 0.
|
||||
- Fixed cTsPayload::AtPayloadStart() to ignore TS packets from other PIDs.
|
||||
- Recordings are now checked for errors:
|
||||
+ On TS level, the continuity counter, transport error indicator and scramble flags are
|
||||
checked.
|
||||
+ On frame level it is checked whether there are no gaps in the PTS.
|
||||
+ The number of errors during a recording is stored in the recording's 'info' file, with
|
||||
the new tag 'O'.
|
||||
+ Spawned timers that shall avoid recording reruns only store the recording's name in
|
||||
the donerecs,data file if there were no errors during recording, and if the timer has
|
||||
actually finished.
|
||||
- Removed the macros __STL_CONFIG_H, _STL_ALGOBASE_H and _MOVE_H from tools.h. If your
|
||||
plugin insists in using "using namespace std;" you can still define
|
||||
DISABLE_TEMPLATES_COLLIDING_WITH_STL before including any VDR header files.
|
||||
- Removed 'register' from libsi/util.c to avoid a warning with ISO-C++17.
|
||||
- The cFile class has been partially deprecated:
|
||||
+ The handling of file handles was not thread-safe.
|
||||
+ It was only actually used in svdrp.c.
|
||||
+ cFile::Ready() now processes only its own file descriptor by calling FileReady()
|
||||
instead of AnyFileReady().
|
||||
- The transponder value of channels is now cached, because cChannel::Transponder(void)
|
||||
is called very often (pointed out by Helmut Binder).
|
||||
- Added code for the 'qad' audio track (thanks to Helmut Binder).
|
||||
- The 'Edit path' dialog now also shows the total size of all recordings in that path
|
||||
(thanks to Christoph Haubrich).
|
||||
- The macro DEPRECATED_VDR_CHARSET_OVERRIDE and the related code has been removed.
|
||||
- The default for DEPRECATED_SETCURRENTCHANNEL has been set to 0, which means that
|
||||
the function SetCurrentChannel(const cChannel *Channel) is no longer available.
|
||||
You can add 'DEPRECATED_SETCURRENTCHANNEL=1' when compiling in order to restore this
|
||||
functionality. However, it is recommended to use SetCurrentChannel(int ChannelNumber)
|
||||
instead.
|
||||
- The macro DEPRECATED_GETBITMAP and the related code has been removed.
|
||||
- The default for DEPRECATED_SKIN_SETITEMEVENT has been set to 0, which means that
|
||||
the function cSkinDisplayMenu::SetItemEvent() without the TimerActive parameter is
|
||||
no longer available. You can add 'DEPRECATED_SKIN_SETITEMEVENT=1' when compiling in
|
||||
order to restore this functionality. However, it is recommended to use the function
|
||||
with the TimerActive parameter instead.
|
||||
|
||||
2021-06-10: Version 2.5.5
|
||||
|
||||
- cRecordingInfo::Errors() now returns -1 for old recordings; added a missing 'const'
|
||||
(suggested by Christoph Haubrich).
|
||||
- The error counter of a recording is now copied as is when editing a recording.
|
||||
- Added missing initialization of cRecorder::lastErrors.
|
||||
- Now using __cplusplus instead of DISABLE_TEMPLATES_COLLIDING_WITH_STL, and using
|
||||
std::min(), std::max() and std::swap() if available (thanks to Winfried Köhler).
|
||||
- No longer permanently looping through PMT PIDs, which caused problems with some
|
||||
SatIP receivers (reported by André Weidemann; with help from Helmut Binder).
|
||||
- Fixed flushing old data from the section handler (thanks to Helmut Binder).
|
||||
- Removed unused declaration of cDvbTuner::SetFrontendType() (thanks to Helmut Binder).
|
||||
- Fixed handling incomplete multi-packet CAT (thanks to Helmut Binder).
|
||||
|
||||
2021-07-02: Version 2.5.6
|
||||
|
||||
- Fixed restarting PMT pids after starting a recording on the currently viewed channel
|
||||
(with help from Helmut Binder).
|
||||
- If an error occurs while recording, the respective entry in the list of recordings is
|
||||
now updated immediately (reported by Matthias Senzel).
|
||||
- Fixed a possible access to characters after the terminating zero of strings in
|
||||
cDoneRecordings::Contains(), in case there are fuzzy characters at the end of a
|
||||
string.
|
||||
- When checking whether a recording has already been made, recording names are now
|
||||
compared case insensitive.
|
||||
- Improved responsiveness in cSectionHandler::Action() (thanks to Helmut Binder).
|
||||
- Fixed deleting the edited recording in case of an error (reported by Christoph Haubrich).
|
||||
- Fixed triggering the PAT filter.
|
||||
- The Recordings menu now marks recordings with errors with an exclamation mark ('!'),
|
||||
and the number of errors (if any) is displayed in the recording's Info menu.
|
||||
|
||||
2021-12-20: Version 2.5.7
|
||||
|
||||
- Replaced all umlauts in the example channels.conf with their ae, oe, ue substitutes
|
||||
to avoid problems on UTF-8 systems.
|
||||
- Added missing '0x09=H.265 video, 0x19 = AC4 audio' to vdr.5 (reported by Christoph
|
||||
Haubrich).
|
||||
- Fixed unlocking vs. call to EpgHandlers.EndSegmentTransfer() (reported by Christoph
|
||||
Haubrich).
|
||||
- Fixed a memory leak in handling the NIT (thanks to Helmut Binder).
|
||||
|
||||
2021-12-27: Version 2.4.8
|
||||
|
||||
- Fixed a possible crash in the Schedule menu, in case Setup.EPGLinger is 0.
|
||||
- Fixed cTsPayload::AtPayloadStart() to ignore TS packets from other PIDs.
|
||||
- Fixed unlocking vs. call to EpgHandlers.EndSegmentTransfer() (reported by Christoph
|
||||
Haubrich).
|
||||
- Fixed a memory leak in handling the NIT (thanks to Helmut Binder).
|
||||
- Fixed a possible memory leak in creating fonts (reported by Helmut Binder).
|
||||
- Fixed calculating the disk use percentage if there's more than 20TB of recordings
|
||||
(reported by Timo Weingärtner).
|
||||
- Official release.
|
||||
|
||||
2021-12-27: Version 2.6.0
|
||||
|
||||
- Fixed a possible memory leak in creating fonts (reported by Helmut Binder).
|
||||
- Fixed calculating the disk use percentage if there's more than 20TB of recordings
|
||||
(reported by Timo Weingärtner).
|
||||
- Official release.
|
||||
|
||||
2022-02-02: Version 2.6.1
|
||||
|
||||
- Replaced strncpy() with memcpy() in strreplace() to avoid a compiler warning
|
||||
(reported by Marko Mäkelä).
|
||||
- Fixed starting replay after jumping to an editing mark.
|
||||
- Updated the Italian OSD texts (thanks to Diego Pierotto).
|
||||
- Added some missing "AUTO" values to vdr.5 (thanks to Winfried Köhler).
|
||||
- Fixed handling zero bytes in cH264Parser (thanks to Christoph Haubrich).
|
||||
- Fixed handling error conditions in the index file (reported by Markus Ehrnsperger).
|
||||
- Fixed a possible deadlock in cDevice::DetachAllReceivers() (thanks to Helmut Binder).
|
||||
- Clarified some potentially mistakable code in cSectionHandler::SetStatus() (pointed
|
||||
out by Onur Sentürk).
|
||||
- Official release.
|
||||
|
||||
2022-11-30: Version 2.6.2
|
||||
|
||||
- Added UPDATE-2.6.0, which was missing in the official 2.6.0 release.
|
||||
- Fixed unexpected calls of the '-r' script when a recording is interrupted and
|
||||
the timer has not yet finished.
|
||||
- Now dropping capabilities after opening terminal.
|
||||
- Now assuming the lock when removing deleted recordings even if the disk is full
|
||||
(reported by Claus Muus).
|
||||
- When checking whether a recording is still active, VDR no longer checks whether the
|
||||
index file is being written, but rather checks for the presence of a '.timer' file.
|
||||
The cutter now writes a dummy '.timer' file with timer ID '0' to make this work
|
||||
for recordings that are currently being edited.
|
||||
- Fixed a possible crash if an editing process is canceled while the edited
|
||||
recording is being replayed.
|
||||
- Added a warning if an attempt is made to obtain a write lock twice from the same thread.
|
||||
- Fixed default values for DVB-T (thanks to Winfried Köhler and Jose Angel).
|
||||
- Removed some unnecessary locks from SVDRPClientHandler.
|
||||
- Fixed a possible deadlock in case two SVDRP clients send each other POLL commands
|
||||
at the same time.
|
||||
- Added a missing 'const' to cTimers::GetTimerForEvent() (reported by Markus Ehrnsperger).
|
||||
- Added a chapter about locking to PLUGINS.html (suggested by Markus Ehrnsperger).
|
||||
- Implemented parsing frame rate and image size for MPEG2, H.264 and H.265 (thanks
|
||||
to Christoph Haubrich).
|
||||
- Using the frame rate parsed from the stream, with fall back to determining it from
|
||||
PTS values.
|
||||
- Fixed printing/scanning values for systems where %ld doesn't work for time_t.
|
||||
- Added support for kernel based LIRC driver (thanks to Marko Mäkelä). Use the
|
||||
command line option '--lirc=/dev/lirc0' to use this. Requires kernel version 5.10
|
||||
or above.
|
||||
- Added periodic calls to malloc_trim(0) to reduce memory consumption (thanks to
|
||||
Onur Sentürk).
|
||||
- Fixed regenerating the index file of a recording in case it is present, but empty
|
||||
(reported by Stefan Herdler).
|
||||
- Added missing rounding when dividing frequencies in processing the NIT (thanks to
|
||||
Winfried Köhler).
|
||||
|
||||
2022-12-14: Version 2.6.3
|
||||
|
||||
- Fixed a compiler warning.
|
||||
- Fixed generating the index file in the cutter (reported by Christoph Haubrich).
|
||||
- Fixed a faulty 'Timer still recording' query when canceling an editing job.
|
||||
- Added code for the 'qks' audio track (thanks to Johann Friedrichs).
|
||||
- Fixed a possible heap-use-after-free in cDvbTuner::Action() (reported by Marko Mäkelä).
|
||||
- Fixed initializing cDvbPlayerControl and cTransferControl (reported by Marko Mäkelä).
|
||||
- Now avoiding calling poll() in cSectionHandler::Action() if there are no filters
|
||||
(reported by Marko Mäkelä).
|
||||
- Now avoiding the memcpy() call in cGlyph::cGlyph() if the bitmap is empty (thanks
|
||||
to Marko Mäkelä).
|
||||
- Now avoiding unnecessary processing in cDvbSubtitleConverter::FinishPage() if there
|
||||
are no areas (thanks to Marko Mäkelä).
|
||||
- Avoiding a zero sized array in cDevice::GetDevice() (thanks to Marko Mäkelä).
|
||||
- Now checking the video directory after setting the user id.
|
||||
|
||||
2023-02-17: Version 2.6.4
|
||||
|
||||
- Updated the Italian OSD texts (thanks to Diego Pierotto).
|
||||
- Fixed restoring the volume at program start (thanks to Matthias Senzel).
|
||||
- Fixed symmetry of Begin/EndSegmentTransfer() calls in cEIT::cEIT() (thanks to
|
||||
Jörg Wendel).
|
||||
- Added a note to epg.h about not messing with event ids (suggested by Winfried Köhler).
|
||||
- Added a note to vdr.5 about event ids possibly changing when an event moves from
|
||||
one table to another.
|
||||
- Fixed initializing cDvbPlayerControl (was broken in version 2.6.3).
|
||||
- Reverted 'Fixed a possible crash if an editing process is canceled while the edited
|
||||
recording is being replayed' (introduced in version 2.6.2), because it caused a
|
||||
deadlock when moving recordings between volumes.
|
||||
- Fixed a possible crash if an editing process is canceled while the edited recording
|
||||
is being replayed (new solution).
|
||||
- Fixed unnecessary interruption of ongoing recordings if timers avoided the transfer
|
||||
mode receiver device (thanks to Markus Ehrnsperger).
|
||||
- Revised support for kernel based LIRC driver (thanks to Marko Mäkelä).
|
||||
|
||||
2023-12-30: Version 2.6.5
|
||||
|
||||
- Fixed broken video data streams on systems without output device when switching live
|
||||
channel to a different transponder while recording (reported by Markus Ehrnsperger).
|
||||
- The frame width, height, scan type and aspect ratio of a recording are now stored in
|
||||
the 'info' file under the 'F' tag (thanks to Christoph Haubrich).
|
||||
- Added the function cRecordingInfo::FrameParams(), which can be used to get a nicely
|
||||
formatted string with all the available frame data.
|
||||
- The recording info of the default skins now shows the frame parameters of the
|
||||
recording at the end of the description (if such information is available).
|
||||
|
||||
2024-01-24: Version 2.6.6
|
||||
|
||||
- Changed installing config files to handle potentially broken 'cp -n'.
|
||||
- Fixed height calculation in progress display (thanks to Matthias Senzel).
|
||||
- Fixed a possible crash in cDevice::StopSectionHandler() (thanks to Markus
|
||||
Ehrnsperger).
|
||||
- Using a dummy OSD if no OSD provider is available is not considered an error any
|
||||
more (thanks to Markus Ehrnsperger).
|
||||
- Implemented scaling images (thanks to Andreas Baierl).
|
||||
- Removed syslog calls in child process after fork() (thanks to Markus Ehrnsperger).
|
||||
- Fixed an unnecessary double display of the current menu item in page up/down
|
||||
(thanks to Matthias Senzel).
|
||||
- Fixed an unnecessary double display of menu items in the Recordings menu (thanks to
|
||||
Matthias Senzel).
|
||||
- Added the move constructor to cString for better performance (thanks to Markus
|
||||
Ehrnsperger).
|
||||
- Added the total number of errors when logging new recording errors.
|
||||
- Added '/' to the list of fuzzy characters for pattern timers.
|
||||
- Fixed handling primary device on headless systems (thanks to Markus Ehrnsperger).
|
||||
- Workaround in detecting frame height for channels with wrong crop parameters
|
||||
(thanks to Christoph Haubrich).
|
||||
- Fixed possible duplicate component entries in the info of an ongoing recording
|
||||
(reported by Christoph Haubrich).
|
||||
|
||||
2024-04-02: Version 2.6.7
|
||||
|
||||
- Fixed the move assignment operator to check for self-assignment (suggested by
|
||||
Stefan Herdler).
|
||||
- Added missing initialization of cChannel::nameSourceMode (thanks to Winfried Köhler).
|
||||
- Modified handling channel names with source to make it thread safe (thanks to
|
||||
Stefan Herdler).
|
||||
- Adapted "Setup/Miscellaneous/Show channel names with source" to the new handling
|
||||
in cChannel.
|
||||
- Added a 15 second grace period before actually stopping a VPS timer (thanks to
|
||||
Markus Ehrnsperger).
|
||||
- The primary device no longer starts unnecessary threads if it doesn't have a decoder
|
||||
(thanks to Markus Ehrnsperger).
|
||||
- The info file of a recording is now re-read if an update of the video directory
|
||||
is triggered, to make sure modifications from other VDRs are adopted.
|
||||
- Updated the Hungarian OSD texts (thanks to István Füley).
|
||||
- The new setup parameters "EPG scan max. channel number" and "EPG pause after scan"
|
||||
can be used to tune the behavior of the EPG scan (see MANUAL for details).
|
||||
- Improved handling present/following data for VPS timers (thanks to Markus Ehrnsperger).
|
||||
- Logging event status changes now also shows the previous status (thanks to Markus
|
||||
Ehrnsperger).
|
||||
- Fixed logging when a timer has entered the VPS margin.
|
||||
- The EIT scan no longer deletes the scanList if no device was switched in this pass.
|
||||
- The EIT scan now skips scanList entries if a device is already tuned to that
|
||||
transponder.
|
||||
- The EIT scan is no longer inhibited if a timer is in VPS margin or needs the
|
||||
transponder.
|
||||
- If the current channel is no longer available because of a VPS timer entering the
|
||||
VPS margin, live view now switches to the channel of that timer.
|
||||
- A device is now always kept occupied if a timer is in VPS margin or needs the
|
||||
transponder (thanks to Markus Ehrnsperger).
|
||||
|
||||
2024-07-08: Version 2.6.8
|
||||
|
||||
- Updated the Italian OSD texts (thanks to Diego Pierotto).
|
||||
- Fixed a possible access of a deleted object in the EIT scanner.
|
||||
- Fixed setting T2 system ID from NIT (thanks to Stefan Herdler).
|
||||
- When starting an editing process, VDR now first checks whether there is enough
|
||||
free disk space to take up the edited version of the recording.
|
||||
- Added an EPG bugfix for broadcasters who put literal "\n" strings in their EPG.
|
||||
Note that the string version of strreplace() has been modified, so that it
|
||||
replaces all occurrences of the search string, not just the first one.
|
||||
- Removed leftover cMenuRecordings::SetPath().
|
||||
- The EIT scanner now checks whether there is a proper device before adding a
|
||||
channel to the scan list.
|
||||
- Unused devices can now be put into a power save mode (suggested by Markus
|
||||
Ehrnsperger). Device plugins need to implement the new function
|
||||
cDevice::SetPowerSaveMode() to make this work.
|
||||
- Implemented power save mode for cDvbDevice (based on a patch from Markus
|
||||
Ehrnsperger).
|
||||
- Added 'lnbPowerTurnedOn = false' to cDvbTuner::ProvidesFrontend() (suggested by
|
||||
Markus Ehrnsperger).
|
||||
|
||||
2024-07-15: Version 2.6.9
|
||||
|
||||
- Fixed a crash in strreplace() for multiple replacements with strings of different
|
||||
lengths (reported by Markus Ehrnsperger).
|
||||
- Fixed handling of cSkinDisplayMenu::GetTextAreaFont() (reported by Matthias Senzel).
|
||||
- Fixed a timeout in cDvbDevice while tuning after the frontend has been reopened.
|
||||
- Fixed setting the editable width in the LCARS skin (reported by Matthias Senzel).
|
||||
- Fixed restarting the EPG scan and keeping the frequency of calls to
|
||||
Device->SetPowerSaveIfUnused() low.
|
||||
- Added the lines from 'Fixed a timeout in cDvbDevice while tuning after the frontend
|
||||
has been reopened' to cDvbTuner::ProvidesFrontend() (suggested by Markus Ehrnsperger).
|
||||
|
||||
2024-09-09: Version 2.7.1
|
||||
|
||||
- Removed deprecated function cDevice::SetCurrentChannel(const cChannel *Channel).
|
||||
- Removed deprecated function cSkinDisplayMenu::SetItemEvent(const cEvent *Event, int Index,
|
||||
bool Current, bool Selectable, const cChannel *Channel, bool WithDate, eTimerMatch TimerMatch).
|
||||
- Removed deprecated functions from cFile.
|
||||
- The default for DEPRECATED_SCHEDULE_GET_EVENT has been set to 0, which means that
|
||||
the function GetEvent(tEventID EventID, time_t StartTime = 0) is no longer available.
|
||||
You can add 'DEPRECATED_SCHEDULE_GET_EVENT=1' when compiling in order to restore this
|
||||
functionality. However, it is recommended to use GetEventById() and GetEventByTime()
|
||||
instead.
|
||||
- The default for DEPRECATED_SECTIONSYNCER_SYNC_REPEAT has been set to 0, which means that
|
||||
the functions Repeat() and Sync() are no longer available.
|
||||
You can add 'DEPRECATED_SECTIONSYNCER_SYNC_REPEAT=1' when compiling in order to restore this
|
||||
functionality. However, it is recommended to use Check() and Processed() instead.
|
||||
- The default for DEPRECATED_CCONTROL has been set to 0, which means that
|
||||
the function Control(bool Hidden) is no longer available.
|
||||
You can add 'DEPRECATED_CCONTROL=1' when compiling in order to restore this
|
||||
functionality. However, it is recommended to use Control(cMutexLock &MutexLock, bool Hidden)
|
||||
instead.
|
||||
- Changed the error message when trying to attach a player to a primary device without
|
||||
an MPEG decoder.
|
||||
- The new SVDRP command 'AUDI' can be used to list the currently available audio tracks
|
||||
and select one of them.
|
||||
- Fixed a crash when deleting a recording that is currently being edited, and then
|
||||
immediately deleting the edited version, too (reported by Marko Mäkelä).
|
||||
- The '.update' file in the video directory is now created if it doesn't already exist.
|
||||
- Improved the error message when closing a frontend (thanks to Markus Ehrnsperger).
|
||||
- There will be no more distinction between "developer" and "stable" versions regarding
|
||||
version numbering. Version numbers are simply counted upwards, with each of the three
|
||||
parts ("version", "major", "minor") always being a single digit, and '0' being skipped.
|
||||
|
||||
2024-09-27: Version 2.7.2
|
||||
|
||||
- Fix for compilers that don't like non-constant format strings (thanks to Stefan Hofmann).
|
||||
- Deprecated code is now marked with [[deprecated]] to issue a compile time warning when
|
||||
used.
|
||||
- Made APIVERSION independent from VDRVERSION to avoid irritation in case only
|
||||
VDRVERSION is incremented (originally suggested by Winfried Köhler, with contributions
|
||||
from Lars Hanisch and Manuel Reimer).
|
||||
APIVERSNUM is now 30003.
|
||||
- Fixed a problem in cSchedule::Sort(), in case hasRunning was true, but there was no event
|
||||
with RunningStatus() >= SI::RunningStatusPausing (reported by Markus Ehrnsperger).
|
||||
- Silenced a compiler warning with gcc 14.1.0 (reported by Winfried Köhler).
|
||||
- Updated the Italian OSD texts (thanks to Diego Pierotto).
|
||||
- Moved error checking from recorder.c to remux.c.
|
||||
- The number of errors in a recording now represents the number of broken frames.
|
||||
- Now distinguishing between frames with errors and completely missing frames.
|
||||
- Recording errors are now marked in the index file.
|
||||
- Fixed description of cSkinDisplayReplay::SetRecording().
|
||||
- Errors are now shown as diamond shaped markers in the replay progress display of the
|
||||
default skins. Plugin authors can switch to the new constructor of cProgressBar to
|
||||
benefit from this feature. Of course this only works with recordings that have error
|
||||
information stored in their index file. If you have existing recordings with errors
|
||||
and want them to be displayed in the progress bar, you can re-generate their index
|
||||
file, either by deleting the old index, or by running vdr with the --genindex option.
|
||||
APIVERSNUM is now 30004.
|
||||
- When the index file of a recording is regenerated, errors in the recording are now
|
||||
stored in the index file.
|
||||
- The info file of an edited recording now contains the number of errors in the edited
|
||||
version. Note that this applies only to recordings that have errors stored in their
|
||||
index file. If errors are not stored in the index file, the edited version will have
|
||||
its number of errors set to that of the original recording.
|
||||
APIVERSNUM is now 30005.
|
||||
- Fixed singular when displaying number of errors in the recording info.
|
||||
- Increased the bpp of cProgressBar to 4 to handle all different colors.
|
||||
- Fixed a problem with duplicate events if they are moved to a lower table ID and at the
|
||||
same time get a new event ID (reported by Markus Ehrnsperger).
|
||||
|
||||
2024-10-12: Version 2.7.3
|
||||
|
||||
- Removed defining DEPRECATED_* macros with value 0, because this is the preprocessor's
|
||||
default (suggested by Winfried Köhler).
|
||||
- Fixed error checking in case of large PTS discontinuities.
|
||||
- Fixed handling negative values in cSource::Position() on systems where 'int' is 64 bit
|
||||
(reported by Markus Ehrnsperger, fix suggested by Winfried Köhler).
|
||||
- Fixed expiring of one-time VPS timers in case there is more than one event with the
|
||||
same VPS time (suggested by Markus Ehrnsperger).
|
||||
- The Channel+/- keys can now be used to jump between errors while replaying a recording
|
||||
(suggested by Stefan Hofmann).
|
||||
- Added vdrrootdir and incdir to vdr.pc (thanks to Stefan Hofmann).
|
||||
|
||||
2025-02-26: Version 2.7.4
|
||||
|
||||
- Removed all DEPRECATED_* code.
|
||||
- Fixed error checking in case the fps value can't be determined by the frame parser.
|
||||
- Updated the Italian OSD texts (thanks to Diego Pierotto).
|
||||
- The VDR homepage is now accessible via HTTPS.
|
||||
- Updated the Finnish OSD texts (thanks to Rolf Ahrenberg).
|
||||
- Fixed some typos in the translation files (thanks to Stefan Hofmann).
|
||||
- Added some missing locking.
|
||||
- TS packets with errors are now skipped when parsing for frames.
|
||||
- Fixed handling the fps value if it can't be determined from the video data.
|
||||
- Fixed accessing a timer's event schedule in case the event has been removed from the
|
||||
schedule.
|
||||
- Fixed a possible deadlock when canceling an editing process.
|
||||
- Checking for VPS control is now limited to local timers.
|
||||
- Added 1 to Utf8BufSize() for worst case (thanks to Stefan Hofmann).
|
||||
- Fixed handling margins for timers that are not VPS controlled and not spawned (thanks
|
||||
to Markus Ehrnsperger).
|
||||
- Added a header to the backtrace (thanks to Stefan Hofmann).
|
||||
- Added parameter checks to strn0cpy() (thanks to Stefan Hofmann). Same for Utf8Strn0Cpy().
|
||||
- The info files of recordings are now only re-read if they have been modified (thanks
|
||||
to Stefan Hofmann).
|
||||
- The new virtual function cStatus::OsdItem2() can be used to get the information whether
|
||||
a menu item is selectable (thanks to Markus Ehrnsperger). Plugins that implemented
|
||||
cStatus::OsdItem() will still work as before, because the default implementation of
|
||||
cStatus::OsdItem2() calls cStatus::OsdItem().
|
||||
APIVERSNUM is now 30006.
|
||||
- Fixed setting the file name of the info file after renaming a recording (reported by
|
||||
Stefan Hofmann).
|
||||
- Fixed an improper call of cStatus::OsdCurrentItem() before cStatus::OsdItem2() (reported
|
||||
by Markus Ehrnsperger).
|
||||
- Fixed an unnecessary redisplay of the menu when pressing a hotkey.
|
||||
- Fixed unnecessary calls to DisplayCurrent() for editable menu items (thanks to Markus
|
||||
Ehrnsperger).
|
||||
- The new virtual function cStatus::OsdCurrentItem2() can be used to get the index of the
|
||||
current menu item (thanks to Markus Ehrnsperger). Plugins that implemented
|
||||
cStatus::OsdCurrentItem() will still work as before, because the default implementation
|
||||
of cStatus::OsdCurrentItem2() calls cStatus::OsdCurrentItem().
|
||||
- Fixed unnecessary calls to cStatus::OsdCurrentItem2() when scrolling.
|
||||
- Added missing calls to cStatus::MsgOsdStatusMessage() and added the new virtual function
|
||||
cStatus::OsdStatusMessage2(), which can be used to get the type of the message (thanks
|
||||
to Markus Ehrnsperger). Plugins that implemented cStatus::OsdStatusMessage() will still
|
||||
work as before, because the default implementation of cStatus::OsdStatusMessage2() calls
|
||||
cStatus::OsdStatusMessage().
|
||||
- Adjusted PLUGINS.html to the new API version numbering introduced in version 2.7.2.
|
||||
- The function cPlugin::MainThreadHook() has been deprecated and may be removed in future
|
||||
versions. Use proper locking instead.
|
||||
- Fixed unnecessary redisplays of menus.
|
||||
- Added '~' to the list of delimiters in cTextWrapper (thanks to Stefan Hofmann).
|
||||
- Fixed progress display when switching from "pause" to "slow back" (reported by Andreas
|
||||
Baierl).
|
||||
- Fixed spurious fast frames when switching from "slow back" to "slow forward".
|
||||
- Fixed cPtsIndex::FindFrameNumber() to handle the case where Pts points to an I-frame.
|
||||
- Added missing locks to SetMenuItem() functions.
|
||||
- Revised locking in cMenuSchedule and cMenuWhatsOn.
|
||||
|
2
INSTALL
2
INSTALL
@ -1,7 +1,7 @@
|
||||
Installation of the Video Disk Recorder
|
||||
---------------------------------------
|
||||
|
||||
Version 2.4
|
||||
Version 2.7
|
||||
-----------
|
||||
|
||||
Compiling and running the program:
|
||||
|
28
MANUAL
28
MANUAL
@ -1,7 +1,7 @@
|
||||
Video Disk Recorder User's Manual
|
||||
---------------------------------
|
||||
|
||||
Version 2.4
|
||||
Version 2.7
|
||||
-----------
|
||||
|
||||
* Remote Control Keys
|
||||
@ -50,8 +50,8 @@ Version 2.4
|
||||
Next Next/previous channel group (in live tv mode)
|
||||
Prev or next/previous editing mark (in replay mode)
|
||||
|
||||
Channel+ channel up
|
||||
Channel- channel down
|
||||
Channel+ channel up (live view), next error (replay)
|
||||
Channel- channel down (live view), previous error (replay)
|
||||
PrevChannel previous channel
|
||||
|
||||
Power shutdown
|
||||
@ -90,7 +90,7 @@ Version 2.4
|
||||
be treated as part of that number, not as a sort mode toggle. If no numeric
|
||||
key has been pressed for more than one second, the number is reset and '0'
|
||||
functions as sort mode toggle again.
|
||||
(3) In the "Timers" menu, when on the "Day" item, the '0' key toggles between
|
||||
(3) In the "Edit timer" menu, when on the "Day" item, the '0' key toggles between
|
||||
a single shot and a repeating timer. If "Day" indicates a repeating timer,
|
||||
the keys '1'...'7' can be used to toggle the individual days ('1' is Monday).
|
||||
|
||||
@ -540,9 +540,9 @@ The following rules apply to pattern timers:
|
||||
with the given start/stop time. Overlapping events are recorded in full,
|
||||
even if they extend outside the given start/stop interval.
|
||||
- In order to actually record an event, a pattern timer "spawns" a separate timer
|
||||
that does the recording. At most two timers are spawned from a pattern timer at
|
||||
any given time, one for the next upcoming matching event, and one for
|
||||
the event immediately following that one, in case it also matches.
|
||||
that does the recording. If there are matching events that would start while
|
||||
the first spawned timer is still recording (due to the start/stop margins), timers
|
||||
for those events are also spawned.
|
||||
- Spawned timers are marked with the flag tfSpawned.
|
||||
- Spawned timers take the Priority, Lifetime and VPS settings from the pattern timer.
|
||||
- The special pattern "*" matches every event. So a timer with
|
||||
@ -556,6 +556,9 @@ The following rules apply to pattern timers:
|
||||
- Recording is done according to the event's begin/end times, either
|
||||
by adding the start/stop margins (for non-VPS timers) or by using the
|
||||
event's running status (for VPS timers).
|
||||
- If the start/stop margins of a spawned timer are reduced because the event
|
||||
before and/or after that timer's event is shorter than the respective margin,
|
||||
the actual recording still uses the full margins.
|
||||
- If the times of the event change, a non-VPS pattern timer automatically adjusts
|
||||
itself to the new times. This also happens if the start/stop margins are changed
|
||||
in the setup.
|
||||
@ -642,6 +645,7 @@ following the matching pattern. There are three macros that can be used here:
|
||||
As of VDR version 2.5.2, the characters ' ' (blank), ':' and '-' are ignored
|
||||
when checking whether a particular recording has already been made by a pattern
|
||||
timer, making "TITLE - EPISODE" and "TITLE: EPISODE" the same.
|
||||
VDR version 2.6.6 added '/' to this list.
|
||||
|
||||
* Managing folders
|
||||
|
||||
@ -825,6 +829,16 @@ timer, making "TITLE - EPISODE" and "TITLE: EPISODE" the same.
|
||||
A value of '0' completely turns off scanning on both single
|
||||
and multiple card systems.
|
||||
|
||||
EPG scan max. channel number = 0
|
||||
The EPG scan will only tune to transponders of channels with
|
||||
numbers below this limit. By default all transponders will
|
||||
be scanned.
|
||||
|
||||
EPG pause after scan = no
|
||||
After a complete scan of all transponders (optionally limited
|
||||
by "EPG scan max. channel number") the EPG scan pauses for
|
||||
"EPG scan timeout" hours if this option is set to "yes".
|
||||
|
||||
EPG bugfix level = 3 Some tv stations transmit weirdly formatted EPG data.
|
||||
VDR attempts to fix these bugs up to the given level:
|
||||
0 = no EPG fixing
|
||||
|
@ -6,7 +6,7 @@
|
||||
# See the main source file 'vdr.c' for copyright information and
|
||||
# how to reach the author.
|
||||
#
|
||||
# $Id: Make.config.template 4.1 2017/06/02 09:29:54 kls Exp $
|
||||
# $Id: Make.config.template 5.2 2024/10/11 14:21:04 kls Exp $
|
||||
|
||||
### The C compiler and options:
|
||||
|
||||
@ -33,14 +33,15 @@ endif
|
||||
# Default directories (adjust as necessary or desired):
|
||||
|
||||
#PREFIX = /usr/local
|
||||
#BINDIR = $(PREFIX)/bin
|
||||
#INCDIR = $(PREFIX)/include
|
||||
#LIBDIR = $(PREFIX)/lib/vdr
|
||||
#LOCDIR = $(PREFIX)/share/locale
|
||||
#MANDIR = $(PREFIX)/share/man
|
||||
#PCDIR = $(PREFIX)/lib/pkgconfig
|
||||
#RESDIR = $(PREFIX)/share/vdr
|
||||
#DVBDIR = /usr/src/v4l-dvb/linux/include/uapi
|
||||
#VDRROOT = $(PREFIX)
|
||||
#BINDIR = $(VDRROOT)/bin
|
||||
#INCDIR = $(VDRROOT)/include
|
||||
#LIBDIR = $(VDRROOT)/lib
|
||||
#LOCDIR = $(VDRROOT)/locale
|
||||
#MANDIR = $(VDRROOT)/man
|
||||
#PCDIR = $(VDRROOT)/pkgconfig
|
||||
#RESDIR = $(VDRROOT)/share
|
||||
#DVBDIR = /usr/include
|
||||
|
||||
#VIDEODIR = /srv/vdr/video
|
||||
#CONFDIR = /var/lib/vdr
|
||||
@ -74,6 +75,8 @@ endif
|
||||
|
||||
### The remote control:
|
||||
LIRC_DEVICE = /var/run/lirc/lircd
|
||||
### Use this for kernel based driver:
|
||||
#LIRC_DEVICE = /dev/lirc0
|
||||
|
||||
### Define if you always want to use LIRC, independent of the --lirc option:
|
||||
#REMOTE=LIRC
|
||||
|
33
Makefile
33
Makefile
@ -4,7 +4,7 @@
|
||||
# See the main source file 'vdr.c' for copyright information and
|
||||
# how to reach the author.
|
||||
#
|
||||
# $Id: Makefile 5.1 2020/12/31 11:11:53 kls Exp $
|
||||
# $Id: Makefile 5.4 2024/10/21 19:01:16 kls Exp $
|
||||
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
@ -46,13 +46,14 @@ ARGSDIR ?= /etc/vdr/conf.d
|
||||
CACHEDIR ?= /var/cache/vdr
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
BINDIR ?= $(PREFIX)/bin
|
||||
INCDIR ?= $(PREFIX)/include
|
||||
LIBDIR ?= $(PREFIX)/lib/vdr
|
||||
LOCDIR ?= $(PREFIX)/share/locale
|
||||
MANDIR ?= $(PREFIX)/share/man
|
||||
PCDIR ?= $(PREFIX)/lib/pkgconfig
|
||||
RESDIR ?= $(PREFIX)/share/vdr
|
||||
VDRROOT ?= $(PREFIX)
|
||||
BINDIR ?= $(VDRROOT)/bin
|
||||
INCDIR ?= $(VDRROOT)/include
|
||||
LIBDIR ?= $(VDRROOT)/lib/vdr
|
||||
LOCDIR ?= $(VDRROOT)/share/locale
|
||||
MANDIR ?= $(VDRROOT)/share/man
|
||||
PCDIR ?= $(VDRROOT)/lib/pkgconfig
|
||||
RESDIR ?= $(VDRROOT)/share/vdr
|
||||
|
||||
# Source documentation
|
||||
|
||||
@ -169,7 +170,9 @@ make-libsi: # empty rule makes sure the sub-make for libsi is always called
|
||||
|
||||
.PHONY: vdr.pc
|
||||
vdr.pc:
|
||||
@echo "bindir=$(BINDIR)" > $@
|
||||
@echo "vdrrootdir=$(VDRROOT)" > $@
|
||||
@echo "bindir=$(BINDIR)" >> $@
|
||||
@echo "incdir=$(INCDIR)" >> $@
|
||||
@echo "mandir=$(MANDIR)" >> $@
|
||||
@echo "videodir=$(VIDEODIR)" >> $@
|
||||
@echo "configdir=$(CONFDIR)" >> $@
|
||||
@ -185,7 +188,7 @@ vdr.pc:
|
||||
@echo "" >> $@
|
||||
@echo "Name: VDR" >> $@
|
||||
@echo "Description: Video Disk Recorder" >> $@
|
||||
@echo "URL: http://www.tvdr.de/" >> $@
|
||||
@echo "URL: https://www.tvdr.de/" >> $@
|
||||
@echo "Version: $(VDRVERSION)" >> $@
|
||||
@echo "Cflags: \$${cflags}" >> $@
|
||||
|
||||
@ -300,7 +303,12 @@ install-dirs:
|
||||
@mkdir -p $(DESTDIR)$(RESDIR)
|
||||
|
||||
install-conf: install-dirs
|
||||
@cp -pn *.conf $(DESTDIR)$(CONFDIR)
|
||||
# 'cp -n' may be broken, so let's do it the hard way
|
||||
@for i in *.conf; do\
|
||||
if ! [ -e $(DESTDIR)$(CONFDIR)/$$i ] ; then\
|
||||
cp -p $$i $(DESTDIR)$(CONFDIR);\
|
||||
fi\
|
||||
done
|
||||
|
||||
# Documentation:
|
||||
|
||||
@ -315,6 +323,7 @@ install-doc:
|
||||
|
||||
install-plugins: plugins
|
||||
@-for i in `ls $(PLUGINDIR)/src | grep -v '[^a-z0-9]'`; do\
|
||||
echo; echo "*** Plugin $$i:";\
|
||||
$(MAKE) --no-print-directory -C "$(PLUGINDIR)/src/$$i" VDRDIR=$(CWD) DESTDIR=$(DESTDIR) install;\
|
||||
done
|
||||
@if [ -d $(PLUGINDIR)/lib ] ; then\
|
||||
@ -351,7 +360,7 @@ srcdoc:
|
||||
clean:
|
||||
@$(MAKE) --no-print-directory -C $(LSIDIR) clean
|
||||
@-rm -f $(OBJS) $(DEPFILE) vdr vdr.pc core* *~
|
||||
@-rm -rf $(LOCALEDIR) $(PODIR)/*.mo $(PODIR)/*.pot
|
||||
@-rm -rf $(LOCALEDIR) $(PODIR)/*~ $(PODIR)/*.mo $(PODIR)/*.pot
|
||||
@-rm -rf include
|
||||
@-rm -rf srcdoc
|
||||
CLEAN: clean
|
||||
|
116
PLUGINS.html
116
PLUGINS.html
@ -31,14 +31,11 @@ modified {
|
||||
<div class="center">
|
||||
<h1>The VDR Plugin System</h1>
|
||||
|
||||
<b>Version 2.4</b>
|
||||
<b>Version 2.7</b>
|
||||
<p>
|
||||
Copyright © 2018 Klaus Schmidinger<br>
|
||||
Copyright © 2021 Klaus Schmidinger<br>
|
||||
<a href="mailto:vdr@tvdr.de">vdr@tvdr.de</a><br>
|
||||
<a href="http://www.tvdr.de">www.tvdr.de</a>
|
||||
</div>
|
||||
<div class="center">
|
||||
<modified>Important modifications introduced since version 2.2 are marked like this.</modified>
|
||||
<a href="https://www.tvdr.de">www.tvdr.de</a>
|
||||
</div>
|
||||
<p>
|
||||
VDR provides an easy to use plugin interface that allows additional functionality
|
||||
@ -77,7 +74,6 @@ structures and allows it to hook itself into specific areas to perform special a
|
||||
<li><a href="#Main menu entry">Main menu entry</a>
|
||||
<li><a href="#User interaction">User interaction</a>
|
||||
<li><a href="#Housekeeping">Housekeeping</a>
|
||||
<li><a href="#Main thread hook">Main thread hook</a>
|
||||
<li><a href="#Activity">Activity</a>
|
||||
<li><a href="#Wakeup">Wakeup</a>
|
||||
<li><a href="#Setup parameters">Setup parameters</a>
|
||||
@ -86,6 +82,7 @@ structures and allows it to hook itself into specific areas to perform special a
|
||||
<li><a href="#Internationalization">Internationalization</a>
|
||||
<li><a href="#Custom services">Custom services</a>
|
||||
<li><a href="#SVDRP commands">SVDRP commands</a>
|
||||
<li><a href="#Locking">Locking</a>
|
||||
<li><a href="#Loading plugins into VDR">Loading plugins into VDR</a>
|
||||
<li><a href="#Building the distribution package">Building the distribution package</a>
|
||||
</ul>
|
||||
@ -168,7 +165,7 @@ is used:
|
||||
VDR/PLUGINS/src
|
||||
VDR/PLUGINS/src/hello
|
||||
VDR/PLUGINS/lib
|
||||
VDR/PLUGINS/lib/libvdr-hello.so.1.1.0
|
||||
VDR/PLUGINS/lib/libvdr-hello.so.1
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
The <tt>src</tt> directory contains one subdirectory for each plugin, which carries
|
||||
@ -187,7 +184,7 @@ The <tt>lib</tt> directory contains the dynamically loadable libraries of all
|
||||
available plugins. Note that the names of these files are created by concatenating
|
||||
<p>
|
||||
<table border=2>
|
||||
<tr><td align=center><b><tt>libvdr-</tt></b></td><td align=center><b><tt>hello</tt></b></td><td align=center><b><tt>.so.</tt></b></td><td align=center><b><tt>1.1.0</tt></b></td></tr>
|
||||
<tr><td align=center><b><tt>libvdr-</tt></b></td><td align=center><b><tt>hello</tt></b></td><td align=center><b><tt>.so.</tt></b></td><td align=center><b><tt>1</tt></b></td></tr>
|
||||
<tr><td align=center><small>VDR plugin<br>library prefix</small></td><td align=center><small>name of<br>the plugin</small></td><td align=center><small>shared object<br>indicator</small></td><td align=center><small>API version number<br>this plugin was<br>compiled for</small></td></tr>
|
||||
</table>
|
||||
<p>
|
||||
@ -198,6 +195,11 @@ the current VDR version. That way minor fixes to VDR, that don't require changes
|
||||
to the VDR header files, can be made without requiring all plugins to be
|
||||
recompiled.
|
||||
<p>
|
||||
While in earlier versions of VDR the API version number was closely related to the
|
||||
VDR version number, starting with VDR version 2.7.2 the API version number was changed
|
||||
from a dot separated, three part number to a single integer, completely unrelated to
|
||||
the VDR version. This was done to avoid confusion.
|
||||
<p>
|
||||
The plugin library files can be stored in any directory. If the default organization
|
||||
is not used, the path to the plugin directory has be be given to VDR through the
|
||||
<b><tt>-L</tt></b> option.
|
||||
@ -393,13 +395,7 @@ just like shown in the above example. This is a convention that allows the <tt>M
|
||||
to extract the version number when generating the file name for the distribution archive.
|
||||
<p>
|
||||
A new plugin project should start with version number <tt>0.0.1</tt> and should reach
|
||||
version <tt>1.0.0</tt> once it is completely operative and well tested. Following the
|
||||
Linux kernel version numbering scheme, versions with <i>even</i> release numbers
|
||||
(like <tt>1.0.x</tt>, <tt>1.2.x</tt>, <tt>1.4.x</tt>...) should be stable releases,
|
||||
while those with <i>odd</i> release numbers (like <tt>1.1.x</tt>, <tt>1.3.x</tt>,
|
||||
<tt>1.5.x</tt>...) are usually considered "under development". The three parts of
|
||||
a version number are not limited to single digits, so a version number of <tt>1.2.15</tt>
|
||||
would be acceptable.
|
||||
version <tt>1.0.0</tt> once it is completely operative and well tested.
|
||||
|
||||
<hr><h2><a name="Description">Description</a></h2>
|
||||
|
||||
@ -584,7 +580,6 @@ esyslog("pluginname: error #%d has occurred", ErrorNumber);
|
||||
Note that the log messages will be given as provided, the plugin's name will not
|
||||
automatically be added, so make sure your log messages are obvious enough.
|
||||
<p>
|
||||
<modified>
|
||||
Only use the above logging functions for occasional log messages. Do not use
|
||||
them unconditionally for frequent messages that produce long sequences of lines
|
||||
in the log file every few seconds. That might make it hard to work on other plugins
|
||||
@ -609,7 +604,6 @@ purpose of the plugin to display something on stdout, like for instance the
|
||||
<br>
|
||||
Please make any log messages in <b>ENGLISH</b>! Logs are usually sent to the developers
|
||||
of a program, and they may not be able to read them if they are in an exotic language.
|
||||
</modified>
|
||||
|
||||
<hr><h2><a name="Main menu entry">Main menu entry</a></h2>
|
||||
|
||||
@ -697,27 +691,6 @@ interaction is possible. If a specific action takes longer than a few seconds,
|
||||
the plugin should launch a separate thread to do this.
|
||||
</b>
|
||||
|
||||
<hr><h2><a name="Main thread hook">Main thread hook</a></h2>
|
||||
|
||||
<div class="blurb">Pushing in...</div><p>
|
||||
|
||||
Normally a plugin only reacts on user input if directly called through its
|
||||
<a href="#Main menu entry">main menu entry</a>, or performs some background
|
||||
activity in a separate thread. However, sometimes a plugin may need to do
|
||||
something in the context of the main program thread, without being explicitly
|
||||
called up by the user. In such a case it can implement the function
|
||||
|
||||
<p><table><tr><td class="code"><pre>
|
||||
virtual void MainThreadHook(void);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
in which it can do this. This function is called for every plugin once during
|
||||
every cycle of VDR's main program loop, which typically happens once every
|
||||
second.
|
||||
<b>Be very careful when using this function, and make sure you return from it
|
||||
as soon as possible! If you spend too much time in this function, the user
|
||||
interface performance will become sluggish!</b>
|
||||
|
||||
<hr><h2><a name="Activity">Activity</a></h2>
|
||||
|
||||
<div class="blurb">Now is not a good time!</div><p>
|
||||
@ -1189,11 +1162,59 @@ The returned string may consist of several lines, separated by the newline chara
|
||||
when presenting them to the caller, and the continuation character ('<tt>-</tt>')
|
||||
will be set for all but the last one.
|
||||
<p>
|
||||
<modified>
|
||||
<b>The SVDRP functions are called from the separate "SVDRP server handler" thread.
|
||||
Therefore the plugin needs to take care of proper locking if it accesses any
|
||||
Therefore the plugin needs to take care of proper <a href="#Locking">locking</a> if it accesses any
|
||||
global data.</b>
|
||||
</modified>
|
||||
|
||||
<hr><h2><a name="Locking">Locking</a></h2>
|
||||
|
||||
<div class="blurb">U can't touch this</div><p>
|
||||
|
||||
When accessing global data structures, proper locking is absolutely necessary.
|
||||
<p>
|
||||
There are several macros that allow for easy locking and unlocking. They all
|
||||
follow the naming convention <tt>LOCK_*_READ|WRITE</tt>, where <tt>'*'</tt> is the name
|
||||
of the global data structure, which can be one of <tt>TIMERS</tt>, <tt>CHANNELS</tt>,
|
||||
<tt>RECORDINGS</tt> or <tt>SCHEDULES</tt>. To implicitly avoid deadlocks in case you
|
||||
need to lock more than one structure, always make sure you use these macros in
|
||||
this sequence!
|
||||
<p>
|
||||
Using one of these macros sets a lock on the structure, creates a local pointer to the
|
||||
respective structure and makes sure the lock is released at the end of the current
|
||||
block:
|
||||
|
||||
<p><table><tr><td class="code"><pre>
|
||||
if (some condition) {
|
||||
LOCK_TIMERS_READ; // creates local const cTimers *Timers
|
||||
for (const cTimer *Timer = Timers->First(); Timer; Timer = Timers->Next(Timer)) {
|
||||
// do something with Timer
|
||||
}
|
||||
}
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
Note the naming convention: TIMERS -> Timers etc.
|
||||
<p>
|
||||
The <tt>LOCK_*_READ</tt> macros create pointers that are '<tt>const</tt>', while
|
||||
the <tt>LOCK_*_WRITE</tt> macros allow modifications to the data structures.
|
||||
Both wait indefinitely to obtain the lock. However, if <tt>LOCK_*_WRITE</tt> is
|
||||
used twice in the same block, the second call will not obtain a lock and
|
||||
immediately return <tt>NULL</tt>, which may lead to a crash. In such cases a
|
||||
warning and backtrace is logged.
|
||||
<p>
|
||||
You may keep pointers to objects in such lists, even after releasing
|
||||
the lock. However, you may only access such objects if you are
|
||||
holding a proper lock again. If an object has been deleted from the list
|
||||
while you did not hold a lock (for instance by an other thread), the
|
||||
object will still be there, but no longer within this list (it is then
|
||||
stored in the ListGarbageCollector for a few seconds). That way even if you
|
||||
access the object after it has been deleted, you won't cause a segfault.
|
||||
You can call the Contains() function to check whether an object you are
|
||||
holding a pointer to is still in the list. Note that the garbage collector
|
||||
is purged when the usual housekeeping is done.
|
||||
<p>
|
||||
See tools.h, class <tt>cListBase</tt> for more documentation and information on how
|
||||
to use locking with timeouts, and thread.h, classes <tt>cStateLock</tt> and
|
||||
<tt>cStateKey</tt> on how to easily react to changes in such lists.
|
||||
|
||||
<hr><h2><a name="Loading plugins into VDR">Loading plugins into VDR</a></h2>
|
||||
|
||||
@ -2073,6 +2094,17 @@ new cMyDeviceHook;
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
and shall not delete this object. It will be automatically deleted when the program ends.
|
||||
<p>
|
||||
<b>Power management</b>
|
||||
<p>
|
||||
A device that can be put into a power save mode can implement the function
|
||||
|
||||
<p><table><tr><td class="code"><pre>
|
||||
virtual void SetPowerSaveMode(bool On);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
If On is true, power save mode shall be activated, if it is false,
|
||||
normal operating mode shall be restored.
|
||||
|
||||
<hr><h2><a name="Positioners">Positioners</a></h2>
|
||||
|
||||
|
@ -28,3 +28,7 @@ VDR Plugin 'epgtableid0' Revision History
|
||||
2018-04-15: Version 2.4.0
|
||||
|
||||
- Official release.
|
||||
|
||||
2021-12-27: Version 2.6.0
|
||||
|
||||
- Official release.
|
||||
|
@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
|
||||
|
||||
Written by: Klaus Schmidinger <vdr@tvdr.de>
|
||||
|
||||
Project's homepage: http://www.tvdr.de
|
||||
Project's homepage: https://www.tvdr.de
|
||||
|
||||
Latest version available at: http://www.tvdr.de
|
||||
Latest version available at: https://www.tvdr.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -99,3 +99,7 @@ VDR Plugin 'hello' Revision History
|
||||
|
||||
- Updated the French OSD texts (thanks to Bernard Jaulin).
|
||||
- Official release.
|
||||
|
||||
2021-12-27: Version 2.6.0
|
||||
|
||||
- Official release.
|
||||
|
@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
|
||||
|
||||
Written by: Klaus Schmidinger <vdr@tvdr.de>
|
||||
|
||||
Project's homepage: http://www.tvdr.de
|
||||
Project's homepage: https://www.tvdr.de
|
||||
|
||||
Latest version available at: http://www.tvdr.de
|
||||
Latest version available at: https://www.tvdr.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,5 +1,5 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Marc Rovira Vall <tm05462@salleURL.edu>, 2003
|
||||
# Ramon Roca <ramon.roca@xcombo.com>, 2003
|
||||
@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Vladimír Bárta <vladimir.barta@k2atmitec.cz>, 2006
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Mogens Elneff <mogens@elneff.dk>, 2004
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Klaus Schmidinger <vdr@tvdr.de>, 2000
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Dimitrios Dimitrakos <mail@dimitrios.de>, 2002
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Ruben Nunez Francisco <ruben.nunez@tang-it.com>, 2002
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Arthur Konovalov <artlov@gmail.com>, 2004, 2015
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,5 +1,5 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Hannu Savolainen <hannu@opensound.com>, 2002
|
||||
# Jaakko Hyvätti <jaakko@hyvatti.iki.fi>, 2002
|
||||
@ -8,7 +8,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,5 +1,5 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Jean-Claude Repetto <jc@repetto.org>, 2001
|
||||
# Olivier Jacques <jacquesolivier@hotmail.com>, 2003
|
||||
@ -9,7 +9,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2018-04-14 8:34+0200\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Adrian Caval <anrxc@sysphere.org>, 2008
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2008-03-17 19:52+0100\n"
|
||||
|
@ -1,12 +1,12 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Istvan Koenigsberger <istvnko@hotmail.com>, 2002
|
||||
# Guido Josten <guido.josten@t-online.de>, 2002
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Diego Pierotto <vdr-italian@tiscali.it>, 2008
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2008-01-27 20:11+0100\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Valdemaras Pipiras <varas@ambernet.lt>, 2009
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2009-12-08 12:18+0200\n"
|
||||
|
@ -1,5 +1,5 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Arnold Niessen <niessen@iae.nl> <arnold.niessen@philips.com>, 2001
|
||||
# Hans Dingemans <hans.dingemans@tacticalops.nl>, 2003
|
||||
@ -7,7 +7,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,12 +1,12 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Jørgen Tvedt <pjtvedt@online.no>, 2001
|
||||
# Truls Slevigen <truls@slevigen.no>, 2002
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,12 +1,12 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Michael Rakowski <mrak@gmx.de>, 2002
|
||||
# Tomasz Maciej Nowak <tmn505@gmail.com>, 2018
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2018-02-19 00:41+0100\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Paulo Lopes <pmml@netvita.pt>, 2001
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,12 +1,12 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Paul Lacatus <paul@campina.iiruc.ro>, 2002
|
||||
# Lucian Muresan <lucianm@users.sourceforge.net>, 2004
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Vyacheslav Dikonov <sdiconov@mail.ru>, 2004
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Vladimír Bárta <vladimir.barta@k2atmitec.cz>, 2006
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2009-09-30 09:48+0100\n"
|
||||
|
@ -1,12 +1,12 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Miha Setina <mihasetina@softhome.net>, 2000
|
||||
# Matjaz Thaler <matjaz.thaler@guest.arnes.si>, 2003
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,12 +1,12 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Tomas Prybil <tomas@prybil.se>, 2002
|
||||
# Jan Ekholm <chakie@infa.abo.fi>, 2003
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2007-08-11 12:34+0200\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Oktay Yolgeçen <oktay_73@yahoo.de>, 2007
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2008-05-12 22:34:4800\n"
|
||||
|
@ -1,5 +1,5 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Marc Rovira Vall <tm05462@salleURL.edu>, 2003
|
||||
# Ramon Roca <ramon.roca@xcombo.com>, 2003
|
||||
@ -8,7 +8,7 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-hello 2.4.0\n"
|
||||
"Project-Id-Version: vdr-hello 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 14:04+0100\n"
|
||||
"PO-Revision-Date: 2009-01-23 09:48+0800\n"
|
||||
|
@ -87,3 +87,7 @@ VDR Plugin 'osddemo' Revision History
|
||||
2020-10-12: Version 2.4.1
|
||||
|
||||
- Added test cases for alignment of semi-circles (press key '4').
|
||||
|
||||
2021-12-27: Version 2.6.0
|
||||
|
||||
- Official release.
|
||||
|
@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
|
||||
|
||||
Written by: Klaus Schmidinger <vdr@tvdr.de>
|
||||
|
||||
Project's homepage: http://www.tvdr.de
|
||||
Project's homepage: https://www.tvdr.de
|
||||
|
||||
Latest version available at: http://www.tvdr.de
|
||||
Latest version available at: https://www.tvdr.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -112,3 +112,11 @@ VDR Plugin 'pictures' Revision History
|
||||
2018-04-15: Version 2.4.0
|
||||
|
||||
- Official release.
|
||||
|
||||
2021-12-27: Version 2.6.0
|
||||
|
||||
- Official release.
|
||||
|
||||
2022-12-05: Version 2.6.1
|
||||
|
||||
Fixed initializing cPictureControl.
|
||||
|
@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
|
||||
|
||||
Written by: Klaus Schmidinger <vdr@tvdr.de>
|
||||
|
||||
Project's homepage: http://www.tvdr.de
|
||||
Project's homepage: https://www.tvdr.de
|
||||
|
||||
Latest version available at: http://www.tvdr.de
|
||||
Latest version available at: https://www.tvdr.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: pictures.c 4.3 2018/04/10 13:00:42 kls Exp $
|
||||
* $Id: pictures.c 5.1 2022/12/05 15:26:23 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -11,7 +11,7 @@
|
||||
#include "menu.h"
|
||||
#include "player.h"
|
||||
|
||||
static const char *VERSION = "2.4.0";
|
||||
static const char *VERSION = "2.6.1";
|
||||
static const char *DESCRIPTION = trNOOP("A simple picture viewer");
|
||||
static const char *MAINMENUENTRY = trNOOP("Pictures");
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: player.c 3.1 2014/02/08 12:48:12 kls Exp $
|
||||
* $Id: player.c 5.1 2022/12/05 15:26:23 kls Exp $
|
||||
*/
|
||||
|
||||
#include "player.h"
|
||||
@ -96,8 +96,10 @@ int cPictureControl::active = 0;
|
||||
cString cPictureControl::lastDisplayed;
|
||||
|
||||
cPictureControl::cPictureControl(cPictureEntry *Pictures, const cPictureEntry *PictureEntry, bool SlideShow)
|
||||
:cControl(player = new cPicturePlayer)
|
||||
:cControl(NULL)
|
||||
{
|
||||
player = new cPicturePlayer;
|
||||
SetPlayer(player);
|
||||
pictures = Pictures;
|
||||
pictureEntry = PictureEntry;
|
||||
osd = NULL;
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Klaus Schmidinger <vdr@tvdr.de>, 2008
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-pictures 2.4.0\n"
|
||||
"Project-Id-Version: vdr-pictures 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 12:57+0100\n"
|
||||
"PO-Revision-Date: 2008-01-12 17:41+0100\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Arthur Konovalov <artlov@gmail.com>, 2015
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-pictures 2.4.0\n"
|
||||
"Project-Id-Version: vdr-pictures 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 12:57+0100\n"
|
||||
"PO-Revision-Date: 2008-01-12 17:41+0100\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Rolf Ahrenberg <Rolf.Ahrenberg@sci.fi>, 2008
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-pictures 2.4.0\n"
|
||||
"Project-Id-Version: vdr-pictures 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 12:57+0100\n"
|
||||
"PO-Revision-Date: 2008-01-12 17:41+0100\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Patrice Staudt <patrice.staudt@laposte.net>, 2008
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-pictures 2.4.0\n"
|
||||
"Project-Id-Version: vdr-pictures 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 12:57+0100\n"
|
||||
"PO-Revision-Date: 2008-01-12 17:41+0100\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Diego Pierotto <vdr-italian@tiscali.it>, 2008
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-pictures 2.4.0\n"
|
||||
"Project-Id-Version: vdr-pictures 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 12:57+0100\n"
|
||||
"PO-Revision-Date: 2008-01-27 20:22+0100\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Valdemaras Pipiras <varas@ambernet.lt>, 2009
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-pictures 2.4.0\n"
|
||||
"Project-Id-Version: vdr-pictures 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 12:57+0100\n"
|
||||
"PO-Revision-Date: 2009-12-08 12:41+0100\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Tomasz Maciej Nowak <tmn505@gmail.com>, 2018
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-pictures 2.4.0\n"
|
||||
"Project-Id-Version: vdr-pictures 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2018-02-19 00:48+0100\n"
|
||||
"PO-Revision-Date: 2018-02-19 00:53+0100\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Alexander Gross <Bikalexander@gmail.com>, 2008
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-pictures 2.4.0\n"
|
||||
"Project-Id-Version: vdr-pictures 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 12:57+0100\n"
|
||||
"PO-Revision-Date: 2008-03-14 00:45+0100\n"
|
||||
|
@ -1,11 +1,11 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Klaus Schmidinger <vdr@tvdr.de>, 2008
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-pictures 2.4.0\n"
|
||||
"Project-Id-Version: vdr-pictures 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2012-12-18 12:57+0100\n"
|
||||
"PO-Revision-Date: 2009-09-30 12:54+0100\n"
|
||||
|
@ -33,3 +33,7 @@ VDR Plugin 'servicedemo' Revision History
|
||||
2018-04-15: Version 2.4.0
|
||||
|
||||
- Official release.
|
||||
|
||||
2021-12-27: Version 2.6.0
|
||||
|
||||
- Official release.
|
||||
|
@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
|
||||
|
||||
Written by: Udo Richter <udo_richter@gmx.de>
|
||||
|
||||
Project's homepage: http://www.tvdr.de
|
||||
Project's homepage: https://www.tvdr.de
|
||||
|
||||
Latest version available at: http://www.tvdr.de
|
||||
Latest version available at: https://www.tvdr.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -152,3 +152,12 @@ VDR Plugin 'skincurses' Revision History
|
||||
- Reacting to changes in screen size.
|
||||
- Simplified color handling.
|
||||
- Using 'stdscr' directly instead of an additional window.
|
||||
|
||||
2021-07-01: Version 2.4.3
|
||||
|
||||
- The number of errors (if any) of a recording is now displayed in the recording's
|
||||
Info menu.
|
||||
|
||||
2021-12-27: Version 2.6.0
|
||||
|
||||
- Official release.
|
||||
|
@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
|
||||
|
||||
Written by: Klaus Schmidinger <vdr@tvdr.de>
|
||||
|
||||
Project's homepage: http://www.tvdr.de
|
||||
Project's homepage: https://www.tvdr.de
|
||||
|
||||
Latest version available at: http://www.tvdr.de
|
||||
Latest version available at: https://www.tvdr.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -1,13 +1,13 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Klaus Schmidinger <vdr@tvdr.de>, 2007
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-skincurses 2.4.0\n"
|
||||
"Project-Id-Version: vdr-skincurses 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2015-02-08 11:16+0100\n"
|
||||
"POT-Creation-Date: 2021-07-01 17:28+0200\n"
|
||||
"PO-Revision-Date: 2007-08-15 16:07+0200\n"
|
||||
"Last-Translator: Klaus Schmidinger <vdr@tvdr.de>\n"
|
||||
"Language-Team: German <vdr@linuxtv.org>\n"
|
||||
@ -19,6 +19,9 @@ msgstr ""
|
||||
msgid "A text only skin"
|
||||
msgstr "Eine reine Text-Oberfläche"
|
||||
|
||||
msgid "errors"
|
||||
msgstr "Fehler"
|
||||
|
||||
msgid "Key$Mute"
|
||||
msgstr "Stumm"
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Arthur Konovalov <artlov@gmail.com>, 2015
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-skincurses 2.4.0\n"
|
||||
"Project-Id-Version: vdr-skincurses 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2015-02-08 11:16+0100\n"
|
||||
"POT-Creation-Date: 2021-07-01 17:28+0200\n"
|
||||
"PO-Revision-Date: 2007-08-14 20:48+0300\n"
|
||||
"Last-Translator: Arthur Konovalov <artlov@gmail.com>\n"
|
||||
"Language-Team: Estonian <vdr@linuxtv.org>\n"
|
||||
@ -19,6 +19,9 @@ msgstr ""
|
||||
msgid "A text only skin"
|
||||
msgstr "Tekstipõhine kest"
|
||||
|
||||
msgid "errors"
|
||||
msgstr ""
|
||||
|
||||
msgid "Key$Mute"
|
||||
msgstr "Hääletu"
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Rolf Ahrenberg <Rolf.Ahrenberg@sci.fi>, 2007
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-skincurses 2.4.0\n"
|
||||
"Project-Id-Version: vdr-skincurses 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2015-02-08 11:16+0100\n"
|
||||
"POT-Creation-Date: 2021-07-01 17:28+0200\n"
|
||||
"PO-Revision-Date: 2007-08-14 20:48+0300\n"
|
||||
"Last-Translator: Rolf Ahrenberg <Rolf.Ahrenberg@sci.fi>\n"
|
||||
"Language-Team: Finnish <vdr@linuxtv.org>\n"
|
||||
@ -19,6 +19,9 @@ msgstr ""
|
||||
msgid "A text only skin"
|
||||
msgstr "Tekstipohjainen ulkoasu"
|
||||
|
||||
msgid "errors"
|
||||
msgstr ""
|
||||
|
||||
msgid "Key$Mute"
|
||||
msgstr "Mykistys"
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Diego Pierotto <vdr-italian@tiscali.it>, 2008
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-skincurses 2.4.0\n"
|
||||
"Project-Id-Version: vdr-skincurses 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2015-02-08 11:16+0100\n"
|
||||
"POT-Creation-Date: 2021-07-01 17:28+0200\n"
|
||||
"PO-Revision-Date: 2008-01-27 20:35+0100\n"
|
||||
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
|
||||
"Language-Team: Italian <vdr@linuxtv.org>\n"
|
||||
@ -19,6 +19,9 @@ msgstr ""
|
||||
msgid "A text only skin"
|
||||
msgstr "Una interfaccia solo testo"
|
||||
|
||||
msgid "errors"
|
||||
msgstr ""
|
||||
|
||||
msgid "Key$Mute"
|
||||
msgstr "Muto"
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Valdemaras Pipiras <varas@ambernet.lt>, 2010
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-skincurses 2.4.0\n"
|
||||
"Project-Id-Version: vdr-skincurses 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2015-02-08 11:16+0100\n"
|
||||
"POT-Creation-Date: 2021-07-01 17:28+0200\n"
|
||||
"PO-Revision-Date: 2010-02-22 18:18+0200\n"
|
||||
"Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n"
|
||||
"Language-Team: Lithuanian <vdr@linuxtv.org>\n"
|
||||
@ -19,6 +19,9 @@ msgstr ""
|
||||
msgid "A text only skin"
|
||||
msgstr "Tekstinis apvalkalas"
|
||||
|
||||
msgid "errors"
|
||||
msgstr ""
|
||||
|
||||
msgid "Key$Mute"
|
||||
msgstr "Išjungti garsą"
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Tomasz Maciej Nowak <tmn505@gmail.com>, 2018
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-skincurses 2.4.0\n"
|
||||
"Project-Id-Version: vdr-skincurses 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2018-02-19 00:48+0100\n"
|
||||
"POT-Creation-Date: 2021-07-01 17:28+0200\n"
|
||||
"PO-Revision-Date: 2018-02-19 01:02+0100\n"
|
||||
"Last-Translator: Tomasz Maciej Nowak <tmn505@gmail.com>\n"
|
||||
"Language-Team: Polish <vdr@linuxtv.org>\n"
|
||||
@ -21,6 +21,9 @@ msgstr ""
|
||||
msgid "A text only skin"
|
||||
msgstr "Skóra tekstowa"
|
||||
|
||||
msgid "errors"
|
||||
msgstr ""
|
||||
|
||||
msgid "Key$Mute"
|
||||
msgstr "Wycisz"
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Alexander Gross <Bikalexander@gmail.com>, 2008
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-skincurses 2.4.0\n"
|
||||
"Project-Id-Version: vdr-skincurses 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2015-02-08 11:16+0100\n"
|
||||
"POT-Creation-Date: 2021-07-01 17:28+0200\n"
|
||||
"PO-Revision-Date: 2008-03-14 00:21+0100\n"
|
||||
"Last-Translator: Alexander Gross <Bikalexander@gmail.com>\n"
|
||||
"Language-Team: Russian <vdr@linuxtv.org>\n"
|
||||
@ -20,6 +20,9 @@ msgstr ""
|
||||
msgid "A text only skin"
|
||||
msgstr "¿àÞáâÞ âÕÚáâÞÒëÙ ØÝâÕàäÕÙá"
|
||||
|
||||
msgid "errors"
|
||||
msgstr ""
|
||||
|
||||
msgid "Key$Mute"
|
||||
msgstr "²ëÚÛ. ÓàÞÜÚÞáâì"
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
# VDR plugin language source file.
|
||||
# Copyright (C) 2018 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# Copyright (C) 2021 Klaus Schmidinger <vdr@tvdr.de>
|
||||
# This file is distributed under the same license as the VDR package.
|
||||
# Klaus Schmidinger <vdr@tvdr.de>, 2007
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: vdr-skincurses 2.4.0\n"
|
||||
"Project-Id-Version: vdr-skincurses 2.6.0\n"
|
||||
"Report-Msgid-Bugs-To: <see README>\n"
|
||||
"POT-Creation-Date: 2015-02-08 11:16+0100\n"
|
||||
"POT-Creation-Date: 2021-07-01 17:28+0200\n"
|
||||
"PO-Revision-Date: 2009-09-30 12:52+0100\n"
|
||||
"Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n"
|
||||
"Language-Team: Slovak <vdr@linuxtv.org>\n"
|
||||
@ -19,6 +19,9 @@ msgstr ""
|
||||
msgid "A text only skin"
|
||||
msgstr "Iba text vzhµadu"
|
||||
|
||||
msgid "errors"
|
||||
msgstr ""
|
||||
|
||||
msgid "Key$Mute"
|
||||
msgstr "Stlmi» zvuk"
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: skincurses.c 4.6 2020/05/11 10:23:15 kls Exp $
|
||||
* $Id: skincurses.c 5.1 2021/07/01 15:40:46 kls Exp $
|
||||
*/
|
||||
|
||||
#include <ncurses.h>
|
||||
@ -12,7 +12,7 @@
|
||||
#include <vdr/skins.h>
|
||||
#include <vdr/videodir.h>
|
||||
|
||||
static const char *VERSION = "2.4.2";
|
||||
static const char *VERSION = "2.4.3";
|
||||
static const char *DESCRIPTION = trNOOP("A text only skin");
|
||||
static const char *MAINMENUENTRY = NULL;
|
||||
|
||||
@ -447,9 +447,18 @@ void cSkinCursesDisplayMenu::SetRecording(const cRecording *Recording)
|
||||
cString t = cString::sprintf("%s %s %s", *DateString(Recording->Start()), *TimeString(Recording->Start()), Info->ChannelName() ? Info->ChannelName() : "");
|
||||
ts.Set(osd, 0, y, ScOsdWidth, ScOsdHeight - y - 2, t, &Font, clrYellow, clrBackground);
|
||||
y += ts.Height();
|
||||
int xt = ScOsdWidth;
|
||||
if (Info->GetEvent()->ParentalRating()) {
|
||||
cString buffer = cString::sprintf(" %s ", *Info->GetEvent()->GetParentalRatingString());
|
||||
osd->DrawText(ScOsdWidth - Utf8StrLen(buffer), y, buffer, clrBlack, clrYellow, &Font);
|
||||
int w = Utf8StrLen(buffer);
|
||||
osd->DrawText(xt - w, y, buffer, clrBlack, clrYellow, &Font);
|
||||
xt -= w + 1;
|
||||
}
|
||||
if (Info->Errors() > 0) {
|
||||
cString buffer = cString::sprintf(" %d %s ", Info->Errors(), tr("errors"));
|
||||
int w = Utf8StrLen(buffer);
|
||||
osd->DrawText(xt - w, y, buffer, clrBlack, clrYellow, &Font);
|
||||
xt -= w + 1;
|
||||
}
|
||||
y += 1;
|
||||
const char *Title = Info->Title();
|
||||
|
@ -72,3 +72,14 @@ VDR Plugin 'status' Revision History
|
||||
2018-04-15: Version 2.4.0
|
||||
|
||||
- Official release.
|
||||
|
||||
2021-12-27: Version 2.6.0
|
||||
|
||||
- Official release.
|
||||
|
||||
2025-02-10: Version 2.6.1
|
||||
|
||||
- Added cStatus::OsdItem2().
|
||||
- Activated logging of OsdItem2().
|
||||
- Added cStatus::OsdCurrentItem2().
|
||||
- Added cStatus::OsdStatusMessage2().
|
||||
|
@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
|
||||
|
||||
Written by: Klaus Schmidinger <vdr@tvdr.de>
|
||||
|
||||
Project's homepage: http://www.tvdr.de
|
||||
Project's homepage: https://www.tvdr.de
|
||||
|
||||
Latest version available at: http://www.tvdr.de
|
||||
Latest version available at: https://www.tvdr.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -3,13 +3,13 @@
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: status.c 4.1 2018/04/10 13:01:03 kls Exp $
|
||||
* $Id: status.c 5.4 2025/02/12 21:18:53 kls Exp $
|
||||
*/
|
||||
|
||||
#include <vdr/plugin.h>
|
||||
#include <vdr/status.h>
|
||||
|
||||
static const char *VERSION = "2.4.0";
|
||||
static const char *VERSION = "2.6.1";
|
||||
static const char *DESCRIPTION = "Status monitor test";
|
||||
static const char *MAINMENUENTRY = NULL;
|
||||
|
||||
@ -27,10 +27,10 @@ protected:
|
||||
virtual void SetSubtitleTrack(int Index, const char * const *Tracks);
|
||||
virtual void OsdClear(void);
|
||||
virtual void OsdTitle(const char *Title);
|
||||
virtual void OsdStatusMessage(const char *Message);
|
||||
virtual void OsdStatusMessage2(eMessageType Type, const char *Message);
|
||||
virtual void OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue);
|
||||
virtual void OsdItem(const char *Text, int Index);
|
||||
virtual void OsdCurrentItem(const char *Text);
|
||||
virtual void OsdItem2(const char *Text, int Index, bool Selectable);
|
||||
virtual void OsdCurrentItem2(const char *Text, int Index);
|
||||
virtual void OsdTextItem(const char *Text, bool Scroll);
|
||||
virtual void OsdChannel(const char *Text);
|
||||
virtual void OsdProgramme(time_t PresentTime, const char *PresentTitle, const char *PresentSubtitle, time_t FollowingTime, const char *FollowingTitle, const char *FollowingSubtitle);
|
||||
@ -86,9 +86,9 @@ void cStatusTest::OsdTitle(const char *Title)
|
||||
dsyslog("status: cStatusTest::OsdTitle '%s'", Title);
|
||||
}
|
||||
|
||||
void cStatusTest::OsdStatusMessage(const char *Message)
|
||||
void cStatusTest::OsdStatusMessage2(eMessageType Type, const char *Message)
|
||||
{
|
||||
dsyslog("status: cStatusTest::OsdStatusMessage '%s'", Message);
|
||||
dsyslog("status: cStatusTest::OsdStatusMessage2 %d '%s'", Type, Message);
|
||||
}
|
||||
|
||||
void cStatusTest::OsdHelpKeys(const char *Red, const char *Green, const char *Yellow, const char *Blue)
|
||||
@ -96,14 +96,14 @@ void cStatusTest::OsdHelpKeys(const char *Red, const char *Green, const char *Ye
|
||||
dsyslog("status: cStatusTest::OsdHelpKeys %s - %s - %s - %s", Red, Green, Yellow, Blue);
|
||||
}
|
||||
|
||||
void cStatusTest::OsdItem(const char *Text, int Index)
|
||||
void cStatusTest::OsdItem2(const char *Text, int Index, bool Selected)
|
||||
{
|
||||
//dsyslog("status: cStatusTest::OsdItem %s %d", Text, Index);
|
||||
dsyslog("status: cStatusTest::OsdItem2 %s %d %d", Text, Index, Selected);
|
||||
}
|
||||
|
||||
void cStatusTest::OsdCurrentItem(const char *Text)
|
||||
void cStatusTest::OsdCurrentItem2(const char *Text, int Index)
|
||||
{
|
||||
dsyslog("status: cStatusTest::OsdCurrentItem %s", Text);
|
||||
dsyslog("status: cStatusTest::OsdCurrentItem %s %d", Text, Index);
|
||||
}
|
||||
|
||||
void cStatusTest::OsdTextItem(const char *Text, bool Scroll)
|
||||
|
@ -37,3 +37,7 @@ VDR Plugin 'svdrpdemo' Revision History
|
||||
2018-04-15: Version 2.4.0
|
||||
|
||||
- Official release.
|
||||
|
||||
2021-12-27: Version 2.6.0
|
||||
|
||||
- Official release.
|
||||
|
@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
|
||||
|
||||
Written by: Klaus Schmidinger <Klaus.Schmidinger@tvdr.de>
|
||||
|
||||
Project's homepage: http://www.tvdr.de
|
||||
Project's homepage: https://www.tvdr.de
|
||||
|
||||
Latest version available at: http://www.tvdr.de
|
||||
Latest version available at: https://www.tvdr.de
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
4
README
4
README
@ -4,7 +4,7 @@ Video Disk Recorder ('VDR')
|
||||
These files contain the source code of the "Video Disk Recorder",
|
||||
which is based on the DVB driver of the LinuxTV project (http://linuxtv.org).
|
||||
For details about the "Video Disk Recorder" project please
|
||||
refer to http://www.tvdr.de.
|
||||
refer to https://www.tvdr.de.
|
||||
|
||||
Please see the INSTALL file for details on how to install
|
||||
this program on your computer.
|
||||
@ -33,7 +33,7 @@ the ones in this system, but here we have the full source code
|
||||
and can modify the menus in whatever way desired.
|
||||
|
||||
If you actually use VDR, please add yourself to the "VDR User Counter"
|
||||
at http://www.tvdr.de/counter.htm. You can also like VDR on facebook
|
||||
at https://www.tvdr.de/counter.htm. You can also like VDR on facebook
|
||||
at https://www.facebook.com/VideoDiskRecorder.
|
||||
|
||||
|
||||
|
@ -10,7 +10,7 @@ Plugins:
|
||||
- Implemented a universal plugin interface. See the file PLUGINS.html
|
||||
for a detailed description. The man page vdr(1) describes the new options '-L'
|
||||
and '-P' used to load plugins.
|
||||
See http://www.tvdr.de/plugins.htm for a list of available plugins.
|
||||
See https://www.tvdr.de/plugins.htm for a list of available plugins.
|
||||
- Rearranged the remote control key handling to allow plugins to implement
|
||||
additional types of remote controls (see PLUGINS.html, section "Remote Control").
|
||||
The previously used files 'keys.conf' and 'keys-pc.conf' have been replaced
|
||||
|
119
UPDATE-2.6.0
Normal file
119
UPDATE-2.6.0
Normal file
@ -0,0 +1,119 @@
|
||||
This is a summary of the changes in VDR 2.6.0 since the last stable
|
||||
version 2.4.0. It only contains things that are of actual importance
|
||||
to the user and doesn't mention the many fixes and improvements that
|
||||
have been made "behind the scenes".
|
||||
|
||||
See the file HISTORY for a detailed list of all changes.
|
||||
|
||||
Timers:
|
||||
|
||||
- Implemented "Pattern Timers" (see MANUAL, vdr.1 and vdr.5 for details).
|
||||
- The margins for timer recordings are now always limited to the duration of the
|
||||
previous and next event.
|
||||
- Spawned timers that don't use VPS now automatically adjust their start/stop times
|
||||
to changes in the respective event's times.
|
||||
|
||||
EPG:
|
||||
|
||||
- Events in the past are no longer marked as having a timer in the Schedules
|
||||
menu.
|
||||
- Improved handling EPG data from the EIT tables:
|
||||
+ Table 0x4F is now completely ignored.
|
||||
+ Once a schedule has seen events from 0x5X, tables 0x6X are ignored for that
|
||||
schedule.
|
||||
+ When looking up an event in its schedule, the start time is used for tables 0x6X, and the
|
||||
event id for tables 0x4E and 0x5X.
|
||||
+ When hashing events by event id or start time, existing older entries in the hash
|
||||
tables are now deleted before entering the new ones.
|
||||
+ The function cSchedule::GetEvent() is now deprecated and may be removed in a future
|
||||
version. Use GetEventById() and GetEventByTime() instead.
|
||||
+ On channels that use proper event ids a change of the start time no longer
|
||||
causes a new event to be created, but rather modifies the existing one. This
|
||||
avoids possible interruptions in VPS recordings in case the event's start time
|
||||
is changed while the recording is already going on.
|
||||
- Fixed the timer indicator in the Schedule menu in case an event is already over, but the
|
||||
timer is still recording.
|
||||
- Fixed unlocking vs. call to EpgHandlers.EndSegmentTransfer().
|
||||
|
||||
Devices:
|
||||
|
||||
- Increased the number of possible modulation systems in cDevice::GetDevice().
|
||||
- Improved cSectionSyncer to make sure that no sections are missed, and to allow
|
||||
handling partially used segments (as in the EIT) and processing sections in random
|
||||
order. Segment syncing is now done with the two member functions Check() and
|
||||
Processed(). The old functions Sync() and Repeat() are deprecated and may be
|
||||
removed in a future version. See the comments in filter.h for a description on
|
||||
how to use these new function.
|
||||
- Added a device hook for detecting whether a device provides EIT data.
|
||||
|
||||
Recordings:
|
||||
|
||||
- Made the functions cRecordingInfo::SetData() and cRecordingInfo::SetAux() public.
|
||||
- Fixed setting the 'title' of a recording's info to the recording's name if there
|
||||
is no info file (the change in version 1.7.28 broke the fallback to the old 'summary.vdr').
|
||||
- Added some missing user command calls for copying, renaming and moving recordings.
|
||||
- Recordings are now checked for errors:
|
||||
+ On TS level, the continuity counter, transport error indicator and scramble flags are
|
||||
checked.
|
||||
+ On frame level it is checked whether there are no gaps in the PTS.
|
||||
+ The number of errors during a recording is stored in the recording's 'info' file, with
|
||||
the new tag 'O'.
|
||||
+ Spawned timers that shall avoid recording reruns only store the recording's name in
|
||||
the donerecs,data file if there were no errors during recording, and if the timer has
|
||||
actually finished.
|
||||
- The Recordings menu now marks recordings with errors with an exclamation mark ('!'),
|
||||
and the number of errors (if any) is displayed in the recording's Info menu.
|
||||
|
||||
Replay:
|
||||
|
||||
- Fixed scaling subtitles with anti-aliasing.
|
||||
|
||||
Conditional Access:
|
||||
|
||||
- Decreased the scrambling timeout for CAMs known to decrypt a certain channel, so
|
||||
that it won't collide with MAXBROKENTIMEOUT in recorder.c.
|
||||
|
||||
Skins:
|
||||
|
||||
- The new functions cTimer::Start/StopTimeEvent() are now used in the LCARS skin to display
|
||||
the start/stop times of timers in the main menu.
|
||||
|
||||
SVDRP:
|
||||
|
||||
- The SVDRP command DELC now also accepts a channel id.
|
||||
|
||||
Misc:
|
||||
|
||||
- Added support for HEVC-video and AC-4-audio.
|
||||
- EXPIRELATENCY now only applies to VPS timers.
|
||||
- Removed the macros __STL_CONFIG_H, _STL_ALGOBASE_H and _MOVE_H from tools.h. If your
|
||||
plugin insists in using "using namespace std;" you can still define
|
||||
DISABLE_TEMPLATES_COLLIDING_WITH_STL before including any VDR header files.
|
||||
- The cFile class has been partially deprecated:
|
||||
+ The handling of file handles was not thread-safe.
|
||||
+ It was only actually used in svdrp.c.
|
||||
+ cFile::Ready() now processes only its own file descriptor by calling FileReady()
|
||||
instead of AnyFileReady().
|
||||
- The transponder value of channels is now cached, because cChannel::Transponder(void)
|
||||
is called very often.
|
||||
- Added code for the 'qad' audio track.
|
||||
- The 'Edit path' dialog now also shows the total size of all recordings in that path.
|
||||
- The macro DEPRECATED_VDR_CHARSET_OVERRIDE and the related code has been removed.
|
||||
- The default for DEPRECATED_SETCURRENTCHANNEL has been set to 0, which means that
|
||||
the function SetCurrentChannel(const cChannel *Channel) is no longer available.
|
||||
You can add 'DEPRECATED_SETCURRENTCHANNEL=1' when compiling in order to restore this
|
||||
functionality. However, it is recommended to use SetCurrentChannel(int ChannelNumber)
|
||||
instead.
|
||||
- The macro DEPRECATED_GETBITMAP and the related code has been removed.
|
||||
- The default for DEPRECATED_SKIN_SETITEMEVENT has been set to 0, which means that
|
||||
the function cSkinDisplayMenu::SetItemEvent() without the TimerActive parameter is
|
||||
no longer available. You can add 'DEPRECATED_SKIN_SETITEMEVENT=1' when compiling in
|
||||
order to restore this functionality. However, it is recommended to use the function
|
||||
with the TimerActive parameter instead.
|
||||
- Now using __cplusplus instead of DISABLE_TEMPLATES_COLLIDING_WITH_STL, and using
|
||||
std::min(), std::max() and std::swap() if available.
|
||||
- No longer permanently looping through PMT PIDs, which caused problems with some
|
||||
SatIP receivers.
|
||||
- Replaced all umlauts in the example channels.conf with their ae, oe, ue substitutes
|
||||
to avoid problems on UTF-8 systems.
|
||||
- Added missing '0x09=H.265 video, 0x19 = AC4 audio' to vdr.5.
|
77
channels.c
77
channels.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: channels.c 4.6 2020/04/11 09:22:05 kls Exp $
|
||||
* $Id: channels.c 5.3 2024/03/02 16:21:16 kls Exp $
|
||||
*/
|
||||
|
||||
#include "channels.h"
|
||||
@ -97,23 +97,32 @@ cChannel& cChannel::operator= (const cChannel &Channel)
|
||||
provider = strcpyrealloc(provider, Channel.provider);
|
||||
portalName = strcpyrealloc(portalName, Channel.portalName);
|
||||
memcpy(&__BeginData__, &Channel.__BeginData__, (char *)&Channel.__EndData__ - (char *)&Channel.__BeginData__);
|
||||
nameSource = NULL; // these will be recalculated automatically
|
||||
nameSourceMode = 0;
|
||||
shortNameSource = NULL;
|
||||
UpdateNameSource();
|
||||
parameters = Channel.parameters;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void cChannel::UpdateNameSource(void)
|
||||
{
|
||||
if (Setup.ShowChannelNamesWithSource == 0) {
|
||||
nameSource = NULL;
|
||||
shortNameSource = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Setup.ShowChannelNamesWithSource == 1)
|
||||
nameSource = cString::sprintf("%s (%c)", name, cSource::ToChar(source));
|
||||
else
|
||||
nameSource = cString::sprintf("%s (%s)", name, *cSource::ToString(source));
|
||||
|
||||
shortNameSource = cString::sprintf("%s (%c)", shortName, cSource::ToChar(source));
|
||||
}
|
||||
|
||||
const char *cChannel::Name(void) const
|
||||
{
|
||||
if (Setup.ShowChannelNamesWithSource && !groupSep) {
|
||||
if (isempty(nameSource) || nameSourceMode != Setup.ShowChannelNamesWithSource) {
|
||||
if (Setup.ShowChannelNamesWithSource == 1)
|
||||
nameSource = cString::sprintf("%s (%c)", name, cSource::ToChar(source));
|
||||
else
|
||||
nameSource = cString::sprintf("%s (%s)", name, *cSource::ToString(source));
|
||||
}
|
||||
return nameSource;
|
||||
if (!isempty(nameSource))
|
||||
return nameSource;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
@ -123,9 +132,8 @@ const char *cChannel::ShortName(bool OrName) const
|
||||
if (OrName && isempty(shortName))
|
||||
return Name();
|
||||
if (Setup.ShowChannelNamesWithSource && !groupSep) {
|
||||
if (isempty(shortNameSource))
|
||||
shortNameSource = cString::sprintf("%s (%c)", shortName, cSource::ToChar(source));
|
||||
return shortNameSource;
|
||||
if (!isempty(shortNameSource))
|
||||
return shortNameSource;
|
||||
}
|
||||
return shortName;
|
||||
}
|
||||
@ -145,15 +153,18 @@ int cChannel::Transponder(int Frequency, char Polarization)
|
||||
|
||||
int cChannel::Transponder(void) const
|
||||
{
|
||||
int tf = frequency;
|
||||
while (tf > 20000)
|
||||
tf /= 1000;
|
||||
if (IsSat()) {
|
||||
const char *p = strpbrk(parameters, "HVLRhvlr"); // lowercase for backwards compatibility
|
||||
if (p)
|
||||
tf = Transponder(tf, *p);
|
||||
if (!transponder) {
|
||||
int tf = frequency;
|
||||
while (tf > 20000)
|
||||
tf /= 1000;
|
||||
if (IsSat()) {
|
||||
const char *p = strpbrk(parameters, "HVLRhvlr"); // lowercase for backwards compatibility
|
||||
if (p)
|
||||
tf = Transponder(tf, *p);
|
||||
}
|
||||
transponder = tf;
|
||||
}
|
||||
return tf;
|
||||
return transponder;
|
||||
}
|
||||
|
||||
int cChannel::Modification(int Mask) const
|
||||
@ -167,6 +178,7 @@ void cChannel::CopyTransponderData(const cChannel *Channel)
|
||||
{
|
||||
if (Channel) {
|
||||
frequency = Channel->frequency;
|
||||
transponder = Channel->transponder;
|
||||
source = Channel->source;
|
||||
srate = Channel->srate;
|
||||
parameters = Channel->parameters;
|
||||
@ -195,12 +207,11 @@ bool cChannel::SetTransponderData(int Source, int Frequency, int Srate, const ch
|
||||
cString OldTransponderData = TransponderDataToString();
|
||||
source = Source;
|
||||
frequency = Frequency;
|
||||
transponder = 0;
|
||||
srate = Srate;
|
||||
parameters = Parameters;
|
||||
schedule = NULL;
|
||||
nameSource = NULL;
|
||||
nameSourceMode = 0;
|
||||
shortNameSource = NULL;
|
||||
UpdateNameSource();
|
||||
if (Number() && !Quiet) {
|
||||
dsyslog("changing transponder data of channel %d (%s) from %s to %s", Number(), name, *OldTransponderData, *TransponderDataToString());
|
||||
modification |= CHANNELMOD_TRANSP;
|
||||
@ -265,15 +276,12 @@ bool cChannel::SetName(const char *Name, const char *ShortName, const char *Prov
|
||||
dsyslog("changing name of channel %d from '%s,%s;%s' to '%s,%s;%s'", Number(), name, shortName, provider, Name, ShortName, Provider);
|
||||
modification |= CHANNELMOD_NAME;
|
||||
}
|
||||
if (nn) {
|
||||
if (nn)
|
||||
name = strcpyrealloc(name, Name);
|
||||
nameSource = NULL;
|
||||
nameSourceMode = 0;
|
||||
}
|
||||
if (ns) {
|
||||
if (ns)
|
||||
shortName = strcpyrealloc(shortName, ShortName);
|
||||
shortNameSource = NULL;
|
||||
}
|
||||
if (nn || ns)
|
||||
UpdateNameSource();
|
||||
if (np)
|
||||
provider = strcpyrealloc(provider, Provider);
|
||||
return true;
|
||||
@ -655,6 +663,7 @@ bool cChannel::Parse(const char *s)
|
||||
if (parambuf && sourcebuf && vpidbuf && apidbuf) {
|
||||
parameters = parambuf;
|
||||
ok = (source = cSource::FromString(sourcebuf)) >= 0;
|
||||
transponder = 0;
|
||||
|
||||
char *p;
|
||||
if ((p = strchr(vpidbuf, '=')) != NULL) {
|
||||
@ -798,9 +807,7 @@ bool cChannel::Parse(const char *s)
|
||||
free(tpidbuf);
|
||||
free(caidbuf);
|
||||
free(namebuf);
|
||||
nameSource = NULL;
|
||||
nameSourceMode = 0;
|
||||
shortNameSource = NULL;
|
||||
UpdateNameSource();
|
||||
if (!GetChannelID().Valid()) {
|
||||
esyslog("ERROR: channel data results in invalid ID!");
|
||||
return false;
|
||||
|
@ -6,10 +6,10 @@ RTL2;CBC:12187:HC34M2S0:S19.2E:27500:166=2:128=deu@3:68;75=deu:0:12020:1:1089:0
|
||||
Das Erste HD;ARD:11493:HC23M5O35P0S1:S19.2E:22000:5101=27:5102=deu@3,5103=mis@3;5106=deu@106:5104;5105=deu:0:10301:1:1019:0
|
||||
ZDF HD;ZDFvision:11362:HC23M5O35P0S1:S19.2E:22000:6110=27:6120=deu@3,6121=mis@3,6123=mul@3;6122=deu@106:6130;6131=deu:0:11110:1:1011:0
|
||||
:Dritte Programme
|
||||
BR Fernsehen Süd HD;ARD:11582:HC23M5O35P0S1:S19.2E:22000:5201=27:5202=deu@3,5203=mis@3;5206=deu@106:5204;5205=deu:0:10325:1:1025:0
|
||||
BR Fernsehen Sued HD;ARD:11582:HC23M5O35P0S1:S19.2E:22000:5201=27:5202=deu@3,5203=mis@3;5206=deu@106:5204;5205=deu:0:10325:1:1025:0
|
||||
hr-fernsehen HD;ARD:10891:HC23M5O35P0S1:S19.2E:22000:5351=27:5352=deu@3,5353=mis@3;5356=deu@106:5354;5355=deu:0:10355:1:1061:0
|
||||
NDR FS NDS HD;ARD:11582:HC23M5O35P0S1:S19.2E:22000:5221=27:5222=deu@3,5223=mis@3;5226=deu@106:5224;5225=deu:0:10327:1:1025:0
|
||||
WDR HD Köln;ARD:12422:HC34M2S0:S19.2E:27500:5501=27:5502=deu@3,5503=mis@3;5506=deu@106:5504;5505=deu:0:28325:1:1201:0
|
||||
WDR HD Koeln;ARD:12422:HC34M2S0:S19.2E:27500:5501=27:5502=deu@3,5503=mis@3;5506=deu@106:5504;5505=deu:0:28325:1:1201:0
|
||||
SWR BW HD;ARD:11493:HC23M5O35P0S1:S19.2E:22000:5121=27:5122=deu@3,5123=mis@3;5126=deu@106:5124;5125=deu:0:10303:1:1019:0
|
||||
rbb Berlin HD;ARD:10891:HC23M5O35P0S1:S19.2E:22000:5311=27:5312=deu@3,5313=mis@3;5316=deu@106:5314;5315=deu:0:10351:1:1061:0
|
||||
MDR Sachsen HD;ARD:10891:HC23M5O35P0S1:S19.2E:22000:5331=27:5332=deu@3,5333=mis@3;5336=deu@106:5334;5335=deu:0:10352:1:1061:0
|
||||
@ -24,7 +24,7 @@ KiKA HD;ZDFvision:11347:VC23M5O35P0S1:S19.2E:22000:6610=27:6620=deu@3,6621=mis@3
|
||||
:Regionalprogramme
|
||||
Niederbayern;MB Satellite:11523:HC56M2S0:S19.2E:22000:2559=2:2560=deu@3:0:0:4609:1:1021:0
|
||||
Franken Fernsehen;MB Satellite:11523:HC56M2S0:S19.2E:22000:511=2:512=deu@3:0:0:4601:1:1021:0
|
||||
münchen.tv;MB Satellite:11523:HC56M2S0:S19.2E:22000:1279=2:1280=deu@3:0:0:4604:1:1021:0
|
||||
muenchen.tv;MB Satellite:11523:HC56M2S0:S19.2E:22000:1279=2:1280=deu@3:0:0:4604:1:1021:0
|
||||
Mainfranken;MB Satellite:11523:HC56M2S0:S19.2E:22000:1791=2:1792=deu@3:0:0:4606:1:1021:0
|
||||
TV Oberfranken;MB Satellite:11523:HC56M2S0:S19.2E:22000:2047=2:2048=deu@3:0:0:4607:1:1021:0
|
||||
TVA-OTV;MB Satellite:11523:HC56M2S0:S19.2E:22000:2303=2:2304=deu@3:0:0:4608:1:1021:0
|
||||
@ -33,7 +33,7 @@ BR Fernsehen Nord HD;ARD:11582:HC23M5O35P0S1:S19.2E:22000:5201=27:5202=deu@3,520
|
||||
rbb Brandenburg HD;ARD:10891:HC23M5O35P0S1:S19.2E:22000:5311=27:5312=deu@3,5313=mis@3;5316=deu@106:5314;5315=deu:0:10350:1:1061:0
|
||||
SR Fernsehen HD;ARD:11052:HC23M5O35P0S1:S19.2E:22000:5431=27:5432=deu@3,5433=mis@3;5436=deu@106:5434;5435=deu:0:10378:1:1039:0
|
||||
Radio Bremen TV;ARD:12421:HC34M2S0:S19.2E:27500:1201=2:1202=deu@3:1204:0:28385:1:1201:0
|
||||
:Österreichisches Fernsehen
|
||||
:Oesterreichisches Fernsehen
|
||||
ORF1 HD;ORF:11303:HC23M5O35P0S1:S19.2E:22000:1920=27:0;1921=deu@106,1922=mis@106:1925:648,650,D95,D98,6E2,500,9C4,98C:4911:1:1007:0
|
||||
ORF2W HD;ORF:11303:HC23M5O35P0S1:S19.2E:22000:2920=27:0;2921=deu@106,2922=mis@106:2925:648,650,D95,D98,6E2,500,9C4,98C:4912:1:1007:0
|
||||
ORF III;ORF:12662:HC56M2S0:S19.2E:22000:1010=2:1011=deu@4:1013:648,650,D95,D98,9C4,98C:13101:1:1115:0
|
||||
@ -159,4 +159,4 @@ Eurosport 2 HD,Eurosp2HD;SKY:11170:HC34M5O35P0S1:S19.2E:22000:1279=27:0;1283=deu
|
||||
Sport1+ HD,Sport1+HD;SKY:12382:HC910M2O35P0S1:S19.2E:27500:1279=27:0;1283=deu@106:0:98C,9C4,98D,9AF:122:133:11:0
|
||||
Sport1 US HD,Sport1USHD;SKY:11332:HC34M5O35P0S1:S19.2E:22000:511=27:0;515=deu@106:32:98C,9C4:119:133:10:0
|
||||
Sky Sport Austria HD,SportAutHD;SKY:11170:HC34M5O35P0S1:S19.2E:22000:1023=27:0;1027=deu@106:0:9C4,98C,98D:143:133:9:0
|
||||
:@1000 Neue Kanäle
|
||||
:@1000 Neue Kanaele
|
||||
|
10
channels.h
10
channels.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: channels.h 5.1 2021/01/14 10:29:05 kls Exp $
|
||||
* $Id: channels.h 5.3 2024/03/02 16:21:16 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CHANNELS_H
|
||||
@ -87,6 +87,7 @@ class cChannels;
|
||||
class cChannel : public cListObject {
|
||||
friend class cSchedules;
|
||||
friend class cMenuEditChannel;
|
||||
friend class cMenuSetupMisc;
|
||||
friend class cDvbSourceParam;
|
||||
private:
|
||||
static cString ToText(const cChannel *Channel);
|
||||
@ -96,6 +97,7 @@ private:
|
||||
char *portalName;
|
||||
int __BeginData__;
|
||||
int frequency; // MHz
|
||||
mutable int transponder; // cached value
|
||||
int source;
|
||||
int srate;
|
||||
int vpid;
|
||||
@ -122,9 +124,8 @@ private:
|
||||
int number; // Sequence number assigned on load
|
||||
bool groupSep;
|
||||
int __EndData__;
|
||||
mutable cString nameSource;
|
||||
mutable int nameSourceMode;
|
||||
mutable cString shortNameSource;
|
||||
cString nameSource;
|
||||
cString shortNameSource;
|
||||
cString parameters;
|
||||
mutable int modification;
|
||||
time_t seen; // When this channel was last seen in the SDT of its transponder
|
||||
@ -132,6 +133,7 @@ private:
|
||||
cLinkChannels *linkChannels;
|
||||
cChannel *refChannel;
|
||||
cString TransponderDataToString(void) const;
|
||||
void UpdateNameSource(void);
|
||||
public:
|
||||
cChannel(void);
|
||||
cChannel(const cChannel &Channel);
|
||||
|
6
ci.c
6
ci.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: ci.c 4.32 2020/08/17 10:26:18 kls Exp $
|
||||
* $Id: ci.c 5.1 2021/06/09 09:41:18 kls Exp $
|
||||
*/
|
||||
|
||||
#include "ci.h"
|
||||
@ -188,6 +188,10 @@ void cCaPidReceiver::Receive(const uchar *Data, int Length)
|
||||
const uchar *p = NULL;
|
||||
if (TsPayloadStart(Data)) {
|
||||
if (Data[5] == SI::TableIdCAT) {
|
||||
if (bufp) { // incomplete multi-packet CAT
|
||||
catVersion = -1;
|
||||
bufp = NULL;
|
||||
}
|
||||
length = (int(Data[6] & 0x0F) << 8) | Data[7]; // section length (12 bit field)
|
||||
if (length > 5) {
|
||||
int v = (Data[10] & 0x3E) >> 1; // version number
|
||||
|
8
config.c
8
config.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.c 4.8 2018/02/15 14:40:36 kls Exp $
|
||||
* $Id: config.c 5.1 2024/03/04 21:13:58 kls Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@ -409,6 +409,8 @@ cSetup::cSetup(void)
|
||||
SubtitleBgTransparency = 0;
|
||||
EPGLanguages[0] = -1;
|
||||
EPGScanTimeout = 5;
|
||||
EPGScanMaxChannel = 0;
|
||||
EPGPauseAfterScan = 0;
|
||||
EPGBugfixLevel = 3;
|
||||
EPGLinger = 0;
|
||||
SVDRPTimeout = 300;
|
||||
@ -637,6 +639,8 @@ bool cSetup::Parse(const char *Name, const char *Value)
|
||||
else if (!strcasecmp(Name, "SubtitleBgTransparency")) SubtitleBgTransparency = atoi(Value);
|
||||
else if (!strcasecmp(Name, "EPGLanguages")) return ParseLanguages(Value, EPGLanguages);
|
||||
else if (!strcasecmp(Name, "EPGScanTimeout")) EPGScanTimeout = atoi(Value);
|
||||
else if (!strcasecmp(Name, "EPGScanMaxChannel")) EPGScanMaxChannel = atoi(Value);
|
||||
else if (!strcasecmp(Name, "EPGPauseAfterScan")) EPGPauseAfterScan = atoi(Value);
|
||||
else if (!strcasecmp(Name, "EPGBugfixLevel")) EPGBugfixLevel = atoi(Value);
|
||||
else if (!strcasecmp(Name, "EPGLinger")) EPGLinger = atoi(Value);
|
||||
else if (!strcasecmp(Name, "SVDRPTimeout")) SVDRPTimeout = atoi(Value);
|
||||
@ -769,6 +773,8 @@ bool cSetup::Save(void)
|
||||
Store("SubtitleBgTransparency", SubtitleBgTransparency);
|
||||
StoreLanguages("EPGLanguages", EPGLanguages);
|
||||
Store("EPGScanTimeout", EPGScanTimeout);
|
||||
Store("EPGScanMaxChannel", EPGScanMaxChannel);
|
||||
Store("EPGPauseAfterScan", EPGPauseAfterScan);
|
||||
Store("EPGBugfixLevel", EPGBugfixLevel);
|
||||
Store("EPGLinger", EPGLinger);
|
||||
Store("SVDRPTimeout", SVDRPTimeout);
|
||||
|
22
config.h
22
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 5.2 2021/04/06 10:04:24 kls Exp $
|
||||
* $Id: config.h 5.26 2025/02/26 10:35:03 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -22,19 +22,21 @@
|
||||
|
||||
// VDR's own version number:
|
||||
|
||||
#define VDRVERSION "2.5.2"
|
||||
#define VDRVERSNUM 20502 // Version * 10000 + Major * 100 + Minor
|
||||
#define VDRVERSION "2.7.4"
|
||||
#define VDRVERSNUM 20704 // Version * 10000 + Major * 100 + Minor
|
||||
|
||||
// The plugin API's version number:
|
||||
|
||||
#define APIVERSION "2.5.2"
|
||||
#define APIVERSNUM 20502 // Version * 10000 + Major * 100 + Minor
|
||||
#define APIVERSION "6"
|
||||
#define APIVERSNUM 30006
|
||||
|
||||
// When loading plugins, VDR searches them by their APIVERSION, which
|
||||
// may be smaller than VDRVERSION in case there have been no changes to
|
||||
// VDR header files since the last APIVERSION. This allows compiled
|
||||
// When loading plugins, VDR searches files by their APIVERSION, which
|
||||
// is different from VDRVERSION. APIVERSION is a plain number, incremented
|
||||
// only when there are changes to the plugin API. This allows compiled
|
||||
// plugins to work with newer versions of the core VDR as long as no
|
||||
// VDR header files have changed.
|
||||
// interfaces have changed. APIVERSNUM begins with "300.." for backwards
|
||||
// compatibility and can be used in #if preprocessor statements to handle
|
||||
// version dependent code.
|
||||
|
||||
#define MAXPRIORITY 99
|
||||
#define MINPRIORITY (-MAXPRIORITY)
|
||||
@ -291,6 +293,8 @@ public:
|
||||
int SubtitleOffset;
|
||||
int SubtitleFgTransparency, SubtitleBgTransparency;
|
||||
int EPGLanguages[I18N_MAX_LANGUAGES + 1];
|
||||
int EPGScanMaxChannel;
|
||||
int EPGPauseAfterScan;
|
||||
int EPGScanTimeout;
|
||||
int EPGBugfixLevel;
|
||||
int EPGLinger;
|
||||
|
66
cutter.c
66
cutter.c
@ -4,12 +4,11 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: cutter.c 4.6 2018/01/18 12:19:31 kls Exp $
|
||||
* $Id: cutter.c 5.4 2025/01/10 13:12:04 kls Exp $
|
||||
*/
|
||||
|
||||
#include "cutter.h"
|
||||
#include "menu.h"
|
||||
#include "recording.h"
|
||||
#include "remux.h"
|
||||
#include "videodir.h"
|
||||
|
||||
@ -232,6 +231,10 @@ private:
|
||||
int numSequences;
|
||||
off_t maxVideoFileSize;
|
||||
off_t fileSize;
|
||||
int frameErrors;
|
||||
time_t lastErrorHandling;
|
||||
cString editedRecordingName;
|
||||
cRecordingInfo *recordingInfo;
|
||||
bool suspensionLogged;
|
||||
int sequence; // cutting sequence
|
||||
int delta; // time between two frames (PTS ticks)
|
||||
@ -246,7 +249,7 @@ private:
|
||||
cPatPmtParser patPmtParser;
|
||||
bool Throttled(void);
|
||||
bool SwitchFile(bool Force = false);
|
||||
bool LoadFrame(int Index, uchar *Buffer, bool &Independent, int &Length);
|
||||
bool LoadFrame(int Index, uchar *Buffer, bool &Independent, int &Length, bool *Errors = NULL, bool *Missing = NULL);
|
||||
bool FramesAreEqual(int Index1, int Index2);
|
||||
void GetPendingPackets(uchar *Buffer, int &Length, int Index);
|
||||
// Gather all non-video TS packets from Index upward that either belong to
|
||||
@ -254,15 +257,16 @@ private:
|
||||
// and add them to the end of the given Data.
|
||||
bool FixFrame(uchar *Data, int &Length, bool Independent, int Index, bool CutIn, bool CutOut);
|
||||
bool ProcessSequence(int LastEndIndex, int BeginIndex, int EndIndex, int NextBeginIndex);
|
||||
void HandleErrors(bool Force = false);
|
||||
protected:
|
||||
virtual void Action(void);
|
||||
public:
|
||||
cCuttingThread(const char *FromFileName, const char *ToFileName);
|
||||
cCuttingThread(const char *FromFileName, const char *ToFileName, cRecordingInfo *RecordingInfo);
|
||||
virtual ~cCuttingThread();
|
||||
const char *Error(void) { return error; }
|
||||
};
|
||||
|
||||
cCuttingThread::cCuttingThread(const char *FromFileName, const char *ToFileName)
|
||||
cCuttingThread::cCuttingThread(const char *FromFileName, const char *ToFileName, cRecordingInfo *RecordingInfo)
|
||||
:cThread("video cutting", true)
|
||||
{
|
||||
error = NULL;
|
||||
@ -274,6 +278,10 @@ cCuttingThread::cCuttingThread(const char *FromFileName, const char *ToFileName)
|
||||
framesPerSecond = Recording.FramesPerSecond();
|
||||
suspensionLogged = false;
|
||||
fileSize = 0;
|
||||
frameErrors = 0;
|
||||
lastErrorHandling = 0;
|
||||
editedRecordingName = ToFileName;
|
||||
recordingInfo = RecordingInfo;
|
||||
sequence = 0;
|
||||
delta = int(round(PTSTICKS / framesPerSecond));
|
||||
lastVidPts = -1;
|
||||
@ -294,6 +302,10 @@ cCuttingThread::cCuttingThread(const char *FromFileName, const char *ToFileName)
|
||||
maxVideoFileSize = MEGABYTE(Setup.MaxVideoFileSize);
|
||||
if (isPesRecording && maxVideoFileSize > MEGABYTE(MAXVIDEOFILESIZEPES))
|
||||
maxVideoFileSize = MEGABYTE(MAXVIDEOFILESIZEPES);
|
||||
if (fromIndex->GetErrors()->Size() > 0) {
|
||||
recordingInfo->SetErrors(0); // the fromIndex has error indicators, so we reset the error count
|
||||
recordingInfo->Write();
|
||||
}
|
||||
Start();
|
||||
}
|
||||
else
|
||||
@ -328,11 +340,11 @@ bool cCuttingThread::Throttled(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cCuttingThread::LoadFrame(int Index, uchar *Buffer, bool &Independent, int &Length)
|
||||
bool cCuttingThread::LoadFrame(int Index, uchar *Buffer, bool &Independent, int &Length, bool *Errors, bool *Missing)
|
||||
{
|
||||
uint16_t FileNumber;
|
||||
off_t FileOffset;
|
||||
if (fromIndex->Get(Index, &FileNumber, &FileOffset, &Independent, &Length)) {
|
||||
if (fromIndex->Get(Index, &FileNumber, &FileOffset, &Independent, &Length, Errors, Missing)) {
|
||||
fromFile = fromFileName->SetOffset(FileNumber, FileOffset);
|
||||
if (fromFile) {
|
||||
fromFile->SetReadAhead(MEGABYTE(20));
|
||||
@ -555,7 +567,9 @@ bool cCuttingThread::ProcessSequence(int LastEndIndex, int BeginIndex, int EndIn
|
||||
for (int Index = BeginIndex; Running() && Index < EndIndex; Index++) {
|
||||
bool Independent;
|
||||
int Length;
|
||||
if (LoadFrame(Index, Buffer, Independent, Length)) {
|
||||
bool Errors;
|
||||
bool Missing;
|
||||
if (LoadFrame(Index, Buffer, Independent, Length, &Errors, &Missing)) {
|
||||
// Make sure there is enough disk space:
|
||||
AssertFreeDiskSpace(-1);
|
||||
bool CutIn = !SeamlessBegin && Index == BeginIndex;
|
||||
@ -572,10 +586,12 @@ bool cCuttingThread::ProcessSequence(int LastEndIndex, int BeginIndex, int EndIn
|
||||
return false;
|
||||
}
|
||||
// Write index:
|
||||
if (!DeletedFrame && !toIndex->Write(Independent, toFileName->Number(), fileSize)) {
|
||||
if (!DeletedFrame && !toIndex->Write(Independent, toFileName->Number(), fileSize, Errors, Missing)) {
|
||||
error = "toIndex";
|
||||
return false;
|
||||
}
|
||||
frameErrors += Errors + Missing;
|
||||
HandleErrors();
|
||||
// Write data:
|
||||
if (toFile->Write(Buffer, Length) < 0) {
|
||||
error = "safe_write";
|
||||
@ -596,6 +612,27 @@ bool cCuttingThread::ProcessSequence(int LastEndIndex, int BeginIndex, int EndIn
|
||||
return true;
|
||||
}
|
||||
|
||||
#define ERROR_HANDLING_DELTA 1 // seconds between handling errors
|
||||
|
||||
void cCuttingThread::HandleErrors(bool Force)
|
||||
{
|
||||
if (Force || time(NULL) - lastErrorHandling >= ERROR_HANDLING_DELTA) {
|
||||
if (frameErrors > recordingInfo->Errors()) {
|
||||
recordingInfo->SetErrors(frameErrors);
|
||||
recordingInfo->Write();
|
||||
Force = true;
|
||||
}
|
||||
if (Force) {
|
||||
cStateKey StateKey;
|
||||
if (cRecordings *Recordings = cRecordings::GetRecordingsWrite(StateKey, 1)) {
|
||||
Recordings->UpdateByName(editedRecordingName);
|
||||
StateKey.Remove();
|
||||
}
|
||||
}
|
||||
lastErrorHandling = time(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void cCuttingThread::Action(void)
|
||||
{
|
||||
if (cMark *BeginMark = fromMarks.GetNextBegin()) {
|
||||
@ -604,6 +641,7 @@ void cCuttingThread::Action(void)
|
||||
if (!fromFile || !toFile)
|
||||
return;
|
||||
int LastEndIndex = -1;
|
||||
HandleErrors(true); // to make sure an initially reset error count is displayed correctly
|
||||
while (BeginMark && Running()) {
|
||||
// Suspend cutting if we have severe throughput problems:
|
||||
if (Throttled()) {
|
||||
@ -634,6 +672,7 @@ void cCuttingThread::Action(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
HandleErrors(true);
|
||||
}
|
||||
else
|
||||
esyslog("no editing marks found!");
|
||||
@ -642,6 +681,7 @@ void cCuttingThread::Action(void)
|
||||
// --- cCutter ---------------------------------------------------------------
|
||||
|
||||
cCutter::cCutter(const char *FileName)
|
||||
:recordingInfo(FileName)
|
||||
{
|
||||
cuttingThread = NULL;
|
||||
error = false;
|
||||
@ -676,8 +716,11 @@ bool cCutter::Start(void)
|
||||
if (strcmp(originalVersionName, editedVersionName) != 0) { // names must be different!
|
||||
cRecordingUserCommand::InvokeCommand(RUC_EDITINGRECORDING, editedVersionName, originalVersionName);
|
||||
if (cVideoDirectory::RemoveVideoFile(editedVersionName) && MakeDirs(editedVersionName, true)) {
|
||||
Recording.WriteInfo(editedVersionName);
|
||||
cuttingThread = new cCuttingThread(originalVersionName, editedVersionName);
|
||||
recordingInfo.Read();
|
||||
recordingInfo.SetFileName(editedVersionName);
|
||||
recordingInfo.Write();
|
||||
SetRecordingTimerId(editedVersionName, cString::sprintf("%d@%s", 0, Setup.SVDRPHostName));
|
||||
cuttingThread = new cCuttingThread(originalVersionName, editedVersionName, &recordingInfo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -693,6 +736,7 @@ void cCutter::Stop(void)
|
||||
const char *Error = cuttingThread ? cuttingThread->Error() : NULL;
|
||||
delete cuttingThread;
|
||||
cuttingThread = NULL;
|
||||
SetRecordingTimerId(editedVersionName, NULL);
|
||||
if ((Interrupted || Error) && *editedVersionName) {
|
||||
if (Interrupted)
|
||||
isyslog("editing process has been interrupted");
|
||||
|
4
cutter.h
4
cutter.h
@ -4,12 +4,13 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: cutter.h 3.1 2013/10/05 11:34:55 kls Exp $
|
||||
* $Id: cutter.h 5.1 2024/09/19 20:21:58 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CUTTER_H
|
||||
#define __CUTTER_H
|
||||
|
||||
#include "recording.h"
|
||||
#include "thread.h"
|
||||
#include "tools.h"
|
||||
|
||||
@ -19,6 +20,7 @@ class cCutter {
|
||||
private:
|
||||
cString originalVersionName;
|
||||
cString editedVersionName;
|
||||
cRecordingInfo recordingInfo;
|
||||
cCuttingThread *cuttingThread;
|
||||
bool error;
|
||||
public:
|
||||
|
131
device.c
131
device.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.c 5.2 2021/03/17 10:59:36 kls Exp $
|
||||
* $Id: device.c 5.14 2024/07/06 11:19:21 kls Exp $
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
@ -95,7 +95,9 @@ cDevice::cDevice(void)
|
||||
|
||||
camSlot = NULL;
|
||||
|
||||
occupiedFrom = 0;
|
||||
occupiedTimeout = 0;
|
||||
occupiedPriority = MINPRIORITY;
|
||||
|
||||
player = NULL;
|
||||
isPlayingVideo = false;
|
||||
@ -249,7 +251,7 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView
|
||||
{
|
||||
// Collect the current priorities of all CAM slots that can decrypt the channel:
|
||||
int NumCamSlots = CamSlots.Count();
|
||||
int SlotPriority[NumCamSlots];
|
||||
int SlotPriority[NumCamSlots + 1]; // +1 to avoid a zero sized array in case there are no CAM slots
|
||||
int NumUsableSlots = 0;
|
||||
bool InternalCamNeeded = false;
|
||||
if (Channel->Ca() >= CA_ENCRYPTED_MIN) {
|
||||
@ -284,8 +286,12 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView
|
||||
continue; // no CAM is able to decrypt this channel and the device uses vdr handled CAMs
|
||||
if (NumUsableSlots && !HasInternalCam && !CamSlots.Get(j)->Assign(device[i], true))
|
||||
continue; // CAM slot can't be used with this device
|
||||
bool ndr;
|
||||
if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basically able to do the job
|
||||
bool ndr = false;
|
||||
bool TunedToTransponder = device[i]->IsTunedToTransponder(Channel);
|
||||
if (TunedToTransponder || device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basically able to do the job
|
||||
bool OccupiedOtherTransponder = !TunedToTransponder && device[i]->Occupied();
|
||||
if (OccupiedOtherTransponder)
|
||||
ndr = true;
|
||||
if (NumUsableSlots && !HasInternalCam) {
|
||||
if (cCamSlot *csi = device[i]->CamSlot()) {
|
||||
cCamSlot *csj = CamSlots.Get(j);
|
||||
@ -303,10 +309,10 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView
|
||||
imp <<= 1; imp |= (LiveView && NumUsableSlots && !HasInternalCam) ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), CamSlots.Get(j)->MasterSlotNumber()) || ndr : 0; // prefer CAMs that are known to decrypt this channel for live viewing, if we don't need to detach existing receivers
|
||||
imp <<= 1; imp |= LiveView ? !device[i]->IsPrimaryDevice() || ndr : 0; // prefer the primary device for live viewing if we don't need to detach existing receivers
|
||||
imp <<= 1; imp |= !device[i]->Receiving() && (device[i] != cTransferControl::ReceiverDevice() || device[i]->IsPrimaryDevice()) || ndr; // use receiving devices if we don't need to detach existing receivers, but avoid primary device in local transfer mode
|
||||
imp <<= 1; imp |= device[i]->Receiving(); // avoid devices that are receiving
|
||||
imp <<= 1; imp |= device[i]->Receiving() || OccupiedOtherTransponder; // avoid devices that are receiving
|
||||
imp <<= 5; imp |= GetClippedNumProvidedSystems(5, device[i]) - 1; // avoid cards which support multiple delivery systems
|
||||
imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice(); // avoid the Transfer Mode receiver device
|
||||
imp <<= 8; imp |= device[i]->Priority() - IDLEPRIORITY; // use the device with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used)
|
||||
imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice(); // avoid the Transfer Mode receiver device
|
||||
imp <<= 8; imp |= ((NumUsableSlots && !HasInternalCam) ? SlotPriority[j] : IDLEPRIORITY) - IDLEPRIORITY;// use the CAM slot with the lowest priority (- IDLEPRIORITY to assure that values -100..99 can be used)
|
||||
imp <<= 1; imp |= ndr; // avoid devices if we need to detach existing receivers
|
||||
imp <<= 1; imp |= (NumUsableSlots || InternalCamNeeded) ? 0 : device[i]->HasCi(); // avoid cards with Common Interface for FTA channels
|
||||
@ -321,6 +327,7 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView
|
||||
if (NumUsableSlots && !HasInternalCam)
|
||||
s = CamSlots.Get(j);
|
||||
}
|
||||
//dsyslog("device %d provides channel %d prio %d ndr %d imp %.8X", device[i]->DeviceNumber() + 1, Channel->Number(), Priority, ndr, imp);
|
||||
}
|
||||
}
|
||||
if (!NumUsableSlots)
|
||||
@ -427,7 +434,8 @@ cDevice *cDevice::GetDeviceForTransponder(const cChannel *Channel, int Priority)
|
||||
if (d->ProvidesTransponder(Channel)) {
|
||||
if (d->MaySwitchTransponder(Channel))
|
||||
return d; // this device may switch to the transponder without disturbing any receiver or live view
|
||||
else if (!d->Occupied() && !d->IsBonded()) { // MaySwitchTransponder() implicitly calls Occupied()
|
||||
else if (!d->Occupied(Priority) && !d->IsBonded() && d->Priority(true) < LIVEPRIORITY) { // MaySwitchTransponder() implicitly calls Occupied()
|
||||
// we select only devices with priority < LIVEPRIORITY, so device can be switched without impact on recordings or live viewing
|
||||
if (d->Priority() < Priority && (!Device || d->Priority() < Device->Priority()))
|
||||
Device = d; // use this one only if no other with less impact can be found
|
||||
}
|
||||
@ -437,6 +445,12 @@ cDevice *cDevice::GetDeviceForTransponder(const cChannel *Channel, int Priority)
|
||||
return Device;
|
||||
}
|
||||
|
||||
void cDevice::ReleaseCamSlot(void)
|
||||
{
|
||||
if (camSlot && !camSlot->IsDecrypting() && !camSlot->IsActivating())
|
||||
camSlot->Assign(NULL);
|
||||
}
|
||||
|
||||
bool cDevice::HasCi(void)
|
||||
{
|
||||
return false;
|
||||
@ -667,11 +681,11 @@ void cDevice::StartSectionHandler(void)
|
||||
void cDevice::StopSectionHandler(void)
|
||||
{
|
||||
if (sectionHandler) {
|
||||
delete sectionHandler; // automatically detaches filters
|
||||
delete nitFilter;
|
||||
delete sdtFilter;
|
||||
delete patFilter;
|
||||
delete eitFilter;
|
||||
delete sectionHandler;
|
||||
nitFilter = NULL;
|
||||
sdtFilter = NULL;
|
||||
patFilter = NULL;
|
||||
@ -795,7 +809,17 @@ bool cDevice::IsTunedToTransponder(const cChannel *Channel) const
|
||||
|
||||
bool cDevice::MaySwitchTransponder(const cChannel *Channel) const
|
||||
{
|
||||
return time(NULL) > occupiedTimeout && !Receiving() && !(pidHandles[ptAudio].pid || pidHandles[ptVideo].pid || pidHandles[ptDolby].pid);
|
||||
return !Occupied() && !Receiving() && !(pidHandles[ptAudio].pid || pidHandles[ptVideo].pid || pidHandles[ptDolby].pid);
|
||||
}
|
||||
|
||||
void cDevice::SetPowerSaveMode(bool On)
|
||||
{
|
||||
}
|
||||
|
||||
void cDevice::SetPowerSaveIfUnused(void)
|
||||
{
|
||||
if (!Occupied() && !Receiving() && !(pidHandles[ptAudio].pid || pidHandles[ptVideo].pid || pidHandles[ptDolby].pid))
|
||||
SetPowerSaveMode(true);
|
||||
}
|
||||
|
||||
bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView)
|
||||
@ -858,12 +882,19 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
|
||||
cStatus::MsgChannelSwitch(this, 0, LiveView);
|
||||
|
||||
if (LiveView) {
|
||||
if (IsPrimaryDevice() && !Replaying() && !Transferring()) { // this is only for FF DVB cards!
|
||||
LOCK_CHANNELS_READ;
|
||||
if (const cChannel *ch = Channels->GetByNumber(currentChannel)) {
|
||||
if (patFilter)
|
||||
patFilter->Release(ch->Sid());
|
||||
}
|
||||
}
|
||||
StopReplay();
|
||||
DELETENULL(liveSubtitle);
|
||||
DELETENULL(dvbSubtitleConverter);
|
||||
}
|
||||
|
||||
cDevice *Device = (LiveView && IsPrimaryDevice()) ? GetDevice(Channel, LIVEPRIORITY, true) : this;
|
||||
cDevice *Device = (LiveView && IsPrimaryDevice(false)) ? GetDevice(Channel, LIVEPRIORITY, true) : this;
|
||||
|
||||
bool NeedsTransferMode = LiveView && Device != PrimaryDevice();
|
||||
// If the CAM slot wants the TS data, we need to switch to Transfer Mode:
|
||||
@ -895,11 +926,10 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
|
||||
// channel to it, for possible later decryption:
|
||||
if (camSlot)
|
||||
camSlot->AddChannel(Channel);
|
||||
SetPowerSaveMode(false);
|
||||
if (SetChannelDevice(Channel, LiveView)) {
|
||||
// Start section handling:
|
||||
if (sectionHandler) {
|
||||
if (patFilter)
|
||||
patFilter->Trigger(Channel->Sid());
|
||||
sectionHandler->SetChannel(Channel);
|
||||
sectionHandler->SetStatus(true);
|
||||
}
|
||||
@ -912,21 +942,26 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
|
||||
}
|
||||
|
||||
if (Result == scrOk) {
|
||||
if (LiveView && IsPrimaryDevice()) {
|
||||
currentChannel = Channel->Number();
|
||||
// Set the available audio tracks:
|
||||
ClrAvailableTracks();
|
||||
for (int i = 0; i < MAXAPIDS; i++)
|
||||
SetAvailableTrack(ttAudio, i, Channel->Apid(i), Channel->Alang(i));
|
||||
if (Setup.UseDolbyDigital) {
|
||||
for (int i = 0; i < MAXDPIDS; i++)
|
||||
SetAvailableTrack(ttDolby, i, Channel->Dpid(i), Channel->Dlang(i));
|
||||
if (LiveView) {
|
||||
if (IsPrimaryDevice(false))
|
||||
currentChannel = Channel->Number();
|
||||
if (IsPrimaryDevice()) {
|
||||
if (patFilter) // this is only for FF DVB cards!
|
||||
patFilter->Request(Channel->Sid());
|
||||
// Set the available audio tracks:
|
||||
ClrAvailableTracks();
|
||||
for (int i = 0; i < MAXAPIDS; i++)
|
||||
SetAvailableTrack(ttAudio, i, Channel->Apid(i), Channel->Alang(i));
|
||||
if (Setup.UseDolbyDigital) {
|
||||
for (int i = 0; i < MAXDPIDS; i++)
|
||||
SetAvailableTrack(ttDolby, i, Channel->Dpid(i), Channel->Dlang(i));
|
||||
}
|
||||
for (int i = 0; i < MAXSPIDS; i++)
|
||||
SetAvailableTrack(ttSubtitle, i, Channel->Spid(i), Channel->Slang(i));
|
||||
if (!NeedsTransferMode)
|
||||
EnsureAudioTrack(true);
|
||||
EnsureSubtitleTrack();
|
||||
}
|
||||
for (int i = 0; i < MAXSPIDS; i++)
|
||||
SetAvailableTrack(ttSubtitle, i, Channel->Spid(i), Channel->Slang(i));
|
||||
if (!NeedsTransferMode)
|
||||
EnsureAudioTrack(true);
|
||||
EnsureSubtitleTrack();
|
||||
}
|
||||
cStatus::MsgChannelSwitch(this, Channel->Number(), LiveView); // only report status if channel switch successful
|
||||
}
|
||||
@ -938,21 +973,34 @@ void cDevice::ForceTransferMode(void)
|
||||
{
|
||||
if (!cTransferControl::ReceiverDevice()) {
|
||||
LOCK_CHANNELS_READ;
|
||||
if (const cChannel *Channel = Channels->GetByNumber(CurrentChannel()))
|
||||
if (const cChannel *Channel = Channels->GetByNumber(CurrentChannel())) {
|
||||
SetPowerSaveMode(false);
|
||||
SetChannelDevice(Channel, false); // this implicitly starts Transfer Mode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cDevice::Occupied(void) const
|
||||
int cDevice::Occupied(int Priority) const
|
||||
{
|
||||
if (Priority > occupiedPriority)
|
||||
return 0;
|
||||
int Seconds = occupiedTimeout - time(NULL);
|
||||
return Seconds > 0 ? Seconds : 0;
|
||||
}
|
||||
|
||||
void cDevice::SetOccupied(int Seconds)
|
||||
void cDevice::SetOccupied(int Seconds, int Priority, time_t From)
|
||||
{
|
||||
if (Seconds >= 0)
|
||||
occupiedTimeout = time(NULL) + min(Seconds, MAXOCCUPIEDTIMEOUT);
|
||||
if (Seconds < 0)
|
||||
return;
|
||||
if (From == 0)
|
||||
From = time(NULL);
|
||||
if (From == occupiedFrom)
|
||||
occupiedPriority = max(Priority, occupiedPriority);
|
||||
else {
|
||||
occupiedPriority = Priority;
|
||||
occupiedFrom = From;
|
||||
}
|
||||
occupiedTimeout = From + min(Seconds, MAXOCCUPIEDTIMEOUT);
|
||||
}
|
||||
|
||||
bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
||||
@ -1581,7 +1629,6 @@ int cDevice::PlayTsSubtitle(const uchar *Data, int Length)
|
||||
return Length;
|
||||
}
|
||||
|
||||
//TODO detect and report continuity errors?
|
||||
int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly)
|
||||
{
|
||||
int Played = 0;
|
||||
@ -1645,11 +1692,13 @@ int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly)
|
||||
return Played;
|
||||
}
|
||||
|
||||
int cDevice::Priority(void) const
|
||||
int cDevice::Priority(bool IgnoreOccupied) const
|
||||
{
|
||||
int priority = IDLEPRIORITY;
|
||||
if (IsPrimaryDevice() && !Replaying() && HasProgramme())
|
||||
priority = TRANSFERPRIORITY; // we use the same value here, no matter whether it's actual Transfer Mode or real live viewing
|
||||
if (!IgnoreOccupied && time(NULL) <= occupiedTimeout && occupiedPriority > priority)
|
||||
priority = occupiedPriority - 1; // so timers with occupiedPriority can start
|
||||
cMutexLock MutexLock(&mutexReceiver);
|
||||
for (int i = 0; i < MAXRECEIVERS; i++) {
|
||||
if (receiver[i])
|
||||
@ -1807,6 +1856,8 @@ bool cDevice::AttachReceiver(cReceiver *Receiver)
|
||||
dsyslog("CAM %d: %sknown to decrypt channel %s (scramblingTimeout = %ds)", camSlot->MasterSlotNumber(), KnownToDecrypt ? "" : "not ", *Receiver->ChannelID().ToString(), Receiver->scramblingTimeout);
|
||||
}
|
||||
}
|
||||
if (patFilter && Receiver->ChannelID().Valid())
|
||||
patFilter->Request(Receiver->ChannelID().Sid());
|
||||
Start();
|
||||
return true;
|
||||
}
|
||||
@ -1815,7 +1866,7 @@ bool cDevice::AttachReceiver(cReceiver *Receiver)
|
||||
return false;
|
||||
}
|
||||
|
||||
void cDevice::Detach(cReceiver *Receiver)
|
||||
void cDevice::Detach(cReceiver *Receiver, bool ReleaseCam)
|
||||
{
|
||||
if (!Receiver || Receiver->device != this)
|
||||
return;
|
||||
@ -1827,6 +1878,8 @@ void cDevice::Detach(cReceiver *Receiver)
|
||||
else if (receiver[i])
|
||||
receiversLeft = true;
|
||||
}
|
||||
if (patFilter && Receiver->ChannelID().Valid())
|
||||
patFilter->Release(Receiver->ChannelID().Sid());
|
||||
mutexReceiver.Unlock();
|
||||
Receiver->device = NULL;
|
||||
Receiver->Activate(false);
|
||||
@ -1835,8 +1888,8 @@ void cDevice::Detach(cReceiver *Receiver)
|
||||
if (camSlot) {
|
||||
if (Receiver->priority > MINPRIORITY) { // priority check to avoid an infinite loop with the CAM slot's caPidReceiver
|
||||
camSlot->StartDecrypting();
|
||||
if (!camSlot->IsDecrypting() && !camSlot->IsActivating())
|
||||
camSlot->Assign(NULL);
|
||||
if (ReleaseCam)
|
||||
ReleaseCamSlot();
|
||||
}
|
||||
}
|
||||
if (!receiversLeft)
|
||||
@ -1850,8 +1903,9 @@ void cDevice::DetachAll(int Pid)
|
||||
for (int i = 0; i < MAXRECEIVERS; i++) {
|
||||
cReceiver *Receiver = receiver[i];
|
||||
if (Receiver && Receiver->WantsPid(Pid))
|
||||
Detach(Receiver);
|
||||
Detach(Receiver, false);
|
||||
}
|
||||
ReleaseCamSlot();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1859,7 +1913,8 @@ void cDevice::DetachAllReceivers(void)
|
||||
{
|
||||
cMutexLock MutexLock(&mutexReceiver);
|
||||
for (int i = 0; i < MAXRECEIVERS; i++)
|
||||
Detach(receiver[i]);
|
||||
Detach(receiver[i], false);
|
||||
ReleaseCamSlot();
|
||||
}
|
||||
|
||||
// --- cTSBuffer -------------------------------------------------------------
|
||||
|
44
device.h
44
device.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.h 4.17 2020/06/27 10:24:46 kls Exp $
|
||||
* $Id: device.h 5.6 2024/07/15 14:42:22 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DEVICE_H
|
||||
@ -178,6 +178,9 @@ public:
|
||||
///< the transponder of the given Channel, without disturbing any receiver
|
||||
///< at priorities higher or equal to Priority.
|
||||
///< If no such device is currently available, NULL will be returned.
|
||||
///< Devices recording (Device->Priority(true) >= LIVEPRIORITY) will not be returned,
|
||||
///< even if Priority >= LIVEPRIORITY. Such higher priorities are only used to
|
||||
///< override occupied.
|
||||
static void Shutdown(void);
|
||||
///< Closes down all devices.
|
||||
///< Must be called at the end of the program.
|
||||
@ -217,7 +220,7 @@ protected:
|
||||
///< May be dropped in a future version, if a better solution is found.
|
||||
///< Do not use otherwise!
|
||||
public:
|
||||
bool IsPrimaryDevice(void) const { return this == primaryDevice && HasDecoder(); }
|
||||
bool IsPrimaryDevice(bool CheckDecoder = true) const { return this == primaryDevice && (!CheckDecoder || HasDecoder()); }
|
||||
int CardIndex(void) const { return cardIndex; }
|
||||
///< Returns the card index of this device (0 ... MAXDEVICES - 1).
|
||||
int DeviceNumber(void) const;
|
||||
@ -259,7 +262,9 @@ public:
|
||||
|
||||
private:
|
||||
mutable cMutex mutexChannel;
|
||||
time_t occupiedFrom;
|
||||
time_t occupiedTimeout;
|
||||
int occupiedPriority;
|
||||
protected:
|
||||
static int currentChannel;
|
||||
public:
|
||||
@ -341,6 +346,14 @@ public:
|
||||
///< device, without disturbing any other activities. If an occupied timeout
|
||||
///< has been set for this device, and that timeout has not yet expired,
|
||||
///< this function returns false.
|
||||
virtual void SetPowerSaveMode(bool On);
|
||||
///< Puts the device into power save mode, if applicable.
|
||||
///< If On is true, power save mode shall be activated, if it is false,
|
||||
///< normal operating mode shall be restored.
|
||||
///< The default implementation does nothing.
|
||||
void SetPowerSaveIfUnused(void);
|
||||
///< Sets this device into a power save mode if it is not currently used and
|
||||
///< has implemented SetPowerSaveMode().
|
||||
bool SwitchChannel(const cChannel *Channel, bool LiveView);
|
||||
///< Switches the device to the given Channel, initiating transfer mode
|
||||
///< if necessary.
|
||||
@ -357,21 +370,16 @@ protected:
|
||||
public:
|
||||
static int CurrentChannel(void) { return primaryDevice ? currentChannel : 0; }
|
||||
///< Returns the number of the current channel on the primary device.
|
||||
#ifndef DEPRECATED_SETCURRENTCHANNEL
|
||||
#define DEPRECATED_SETCURRENTCHANNEL 1
|
||||
#endif
|
||||
#if DEPRECATED_SETCURRENTCHANNEL
|
||||
static void SetCurrentChannel(const cChannel *Channel) { currentChannel = Channel ? Channel->Number() : 0; }
|
||||
#endif
|
||||
static void SetCurrentChannel(int ChannelNumber) { currentChannel = ChannelNumber; }
|
||||
///< Sets the number of the current channel on the primary device, without
|
||||
///< actually switching to it. This can be used to correct the current
|
||||
///< channel number while replaying.
|
||||
void ForceTransferMode(void);
|
||||
///< Forces the device into transfermode for the current channel.
|
||||
int Occupied(void) const;
|
||||
///< Returns the number of seconds this device is still occupied for.
|
||||
void SetOccupied(int Seconds);
|
||||
int Occupied(int Priority = MINPRIORITY) const;
|
||||
///< Returns the number of seconds this device is still occupied for
|
||||
///< with a priority >= Priority.
|
||||
void SetOccupied(int Seconds, int Priority = MINPRIORITY, time_t From = 0);
|
||||
///< Sets the occupied timeout for this device to the given number of
|
||||
///< Seconds, This can be used to tune a device to a particular transponder
|
||||
///< and make sure it will stay there for a certain amount of time, for
|
||||
@ -379,6 +387,10 @@ public:
|
||||
///< after the device has been successfully tuned to the requested transponder.
|
||||
///< Seconds will be silently limited to MAXOCCUPIEDTIMEOUT. Values less than
|
||||
///< 0 will be silently ignored.
|
||||
///< The timeout is counted from the given From time (by default the current time).
|
||||
///< Calling this function several times with the same From time will set the
|
||||
///< priority to the maximum of the given values.
|
||||
///< Priority() may return a value >= Priority until the timeout.
|
||||
virtual bool HasLock(int TimeoutMs = 0) const;
|
||||
///< Returns true if the device has a lock on the requested transponder.
|
||||
///< Default is true, a specific device implementation may return false
|
||||
@ -465,6 +477,8 @@ public:
|
||||
|
||||
private:
|
||||
cCamSlot *camSlot;
|
||||
void ReleaseCamSlot(void);
|
||||
///< Releases the CAM slot if it is currently not used.
|
||||
public:
|
||||
virtual bool HasCi(void);
|
||||
///< Returns true if this device has a Common Interface.
|
||||
@ -831,9 +845,10 @@ private:
|
||||
mutable cMutex mutexReceiver;
|
||||
cReceiver *receiver[MAXRECEIVERS];
|
||||
public:
|
||||
int Priority(void) const;
|
||||
int Priority(bool IgnoreOccupied = false) const;
|
||||
///< Returns the priority of the current receiving session (-MAXPRIORITY..MAXPRIORITY),
|
||||
///< or IDLEPRIORITY if no receiver is currently active.
|
||||
///< If IgnoreOccupied is true, a priority set with SetOccupied() is ignored.
|
||||
protected:
|
||||
virtual bool OpenDvr(void);
|
||||
///< Opens the DVR of this device and prepares it to deliver a Transport
|
||||
@ -852,8 +867,11 @@ public:
|
||||
///< Returns true if we are currently receiving. The parameter has no meaning (for backwards compatibility only).
|
||||
bool AttachReceiver(cReceiver *Receiver);
|
||||
///< Attaches the given receiver to this device.
|
||||
void Detach(cReceiver *Receiver);
|
||||
void Detach(cReceiver *Receiver, bool ReleaseCam = true);
|
||||
///< Detaches the given receiver from this device.
|
||||
///< If ReleaseCam is true, the CAM slot will be released if it
|
||||
///< is no longer used. Otherwise the caller must call ReleaseCamSlot() after
|
||||
///< calling this function.
|
||||
void DetachAll(int Pid);
|
||||
///< Detaches all receivers from this device for this pid.
|
||||
virtual void DetachAllReceivers(void);
|
||||
|
69
dvbdevice.c
69
dvbdevice.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.c 4.29 2020/12/05 15:48:40 kls Exp $
|
||||
* $Id: dvbdevice.c 5.8 2024/09/09 08:53:57 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbdevice.h"
|
||||
@ -23,6 +23,8 @@
|
||||
|
||||
static int DvbApiVersion = 0x0000; // the version of the DVB driver actually in use (will be determined by the first device created)
|
||||
|
||||
#define BANDWIDTH_HZ_AUTO 0 // missing in DVB API 5
|
||||
|
||||
#define DVBS_TUNE_TIMEOUT 9000 //ms
|
||||
#define DVBS_LOCK_TIMEOUT 2000 //ms
|
||||
#define DVBC_TUNE_TIMEOUT 9000 //ms
|
||||
@ -59,6 +61,7 @@ const tDvbParameterMap BandwidthValues[] = {
|
||||
{ 8, 8000000, "8 MHz" },
|
||||
{ 10, 10000000, "10 MHz" },
|
||||
{ 1712, 1712000, "1.712 MHz" },
|
||||
{ 999, BANDWIDTH_HZ_AUTO, trNOOP("auto") },
|
||||
{ -1, 0, NULL }
|
||||
};
|
||||
|
||||
@ -255,10 +258,10 @@ bool cDvbTransponderParameters::Parse(const char *s)
|
||||
{
|
||||
polarization = 0;
|
||||
inversion = INVERSION_AUTO;
|
||||
bandwidth = 8000000;
|
||||
bandwidth = BANDWIDTH_HZ_AUTO;
|
||||
coderateH = FEC_AUTO;
|
||||
coderateL = FEC_AUTO;
|
||||
modulation = QPSK;
|
||||
modulation = QAM_AUTO;
|
||||
system = DVB_SYSTEM_1;
|
||||
transmission = TRANSMISSION_MODE_AUTO;
|
||||
guard = GUARD_INTERVAL_AUTO;
|
||||
@ -391,7 +394,7 @@ void cDvbFrontend::Close(void)
|
||||
{
|
||||
if (fd_frontend >= 0) {
|
||||
if (close(fd_frontend) != 0)
|
||||
esyslog("ERROR: frontend %d/%d", adapter, frontend);
|
||||
esyslog("ERROR: frontend %d/%d: %m (%s:%d)", adapter, frontend, __FILE__, __LINE__);
|
||||
fd_frontend = -1;
|
||||
}
|
||||
}
|
||||
@ -546,19 +549,18 @@ private:
|
||||
mutable uint32_t lastUncDelta;
|
||||
mutable time_t lastUncChange;
|
||||
cChannel channel;
|
||||
const cDiseqc *lastDiseqc;
|
||||
mutable const cDiseqc *lastDiseqc;
|
||||
int diseqcOffset;
|
||||
int lastSource;
|
||||
mutable int lastSource;
|
||||
cPositioner *positioner;
|
||||
const cScr *scr;
|
||||
bool lnbPowerTurnedOn;
|
||||
mutable bool lnbPowerTurnedOn;
|
||||
eTunerStatus tunerStatus;
|
||||
mutable cMutex mutex;
|
||||
cCondVar locked;
|
||||
cCondVar newSet;
|
||||
cDvbTuner *bondedTuner;
|
||||
bool bondedMaster;
|
||||
bool SetFrontendType(const cChannel *Channel);
|
||||
cString GetBondingParams(const cChannel *Channel = NULL) const;
|
||||
cDvbTuner *GetBondedMaster(void);
|
||||
bool IsBondedMaster(void) const { return !bondedTuner || bondedMaster; }
|
||||
@ -591,6 +593,7 @@ public:
|
||||
bool GetSignalStats(int &Valid, double *Strength = NULL, double *Cnr = NULL, double *BerPre = NULL, double *BerPost = NULL, double *Per = NULL, int *Status = NULL) const;
|
||||
int GetSignalStrength(void) const;
|
||||
int GetSignalQuality(void) const;
|
||||
void SetPowerSaveMode(bool On);
|
||||
};
|
||||
|
||||
cMutex cDvbTuner::bondMutex;
|
||||
@ -694,9 +697,12 @@ bool cDvbTuner::ProvidesFrontend(const cChannel *Channel, bool Activate) const
|
||||
fd_frontend = dvbFrontend->Open();
|
||||
frontend = i;
|
||||
dsyslog("using frontend %d/%d", adapter, frontend);
|
||||
lastDiseqc = NULL;
|
||||
lastSource = 0;
|
||||
lastUncValue = 0;
|
||||
lastUncDelta = 0;
|
||||
lastUncChange = 0;
|
||||
lnbPowerTurnedOn = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -857,6 +863,8 @@ void cDvbTuner::ClearEventQueue(void) const
|
||||
|
||||
bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const
|
||||
{
|
||||
if (fd_frontend == -1)
|
||||
return false;
|
||||
ClearEventQueue();
|
||||
Status = (fe_status_t)0; // initialize here to fix buggy drivers
|
||||
while (1) {
|
||||
@ -874,6 +882,8 @@ bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const
|
||||
|
||||
bool cDvbTuner::GetSignalStats(int &Valid, double *Strength, double *Cnr, double *BerPre, double *BerPost, double *Per, int *Status) const
|
||||
{
|
||||
if (fd_frontend == -1)
|
||||
return false;
|
||||
ClearEventQueue();
|
||||
fe_status_t FeStatus = (fe_status_t)0; // initialize here to fix buggy drivers
|
||||
dtv_property Props[MAXFRONTENDCMDS];
|
||||
@ -1224,6 +1234,8 @@ int SignalToSQI(const cChannel *Channel, int Signal, int Ber, int FeModulation,
|
||||
|
||||
int cDvbTuner::GetSignalStrength(void) const
|
||||
{
|
||||
if (fd_frontend == -1)
|
||||
return 0;
|
||||
ClearEventQueue();
|
||||
// Try DVB API 5:
|
||||
for (int i = 0; i < 1; i++) { // just a trick to break out with 'continue' ;-)
|
||||
@ -1289,6 +1301,8 @@ int cDvbTuner::GetSignalStrength(void) const
|
||||
|
||||
int cDvbTuner::GetSignalQuality(void) const
|
||||
{
|
||||
if (fd_frontend == -1)
|
||||
return 0;
|
||||
// Try DVB API 5:
|
||||
for (int i = 0; i < 1; i++) { // just a trick to break out with 'continue' ;-)
|
||||
dtv_property Props[MAXFRONTENDCMDS];
|
||||
@ -1534,6 +1548,8 @@ void cDvbTuner::ExecuteDiseqc(const cDiseqc *Diseqc, int *Frequency)
|
||||
|
||||
void cDvbTuner::ResetToneAndVoltage(void)
|
||||
{
|
||||
if (fd_frontend == -1)
|
||||
return;
|
||||
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, bondedTuner ? SEC_VOLTAGE_OFF : SEC_VOLTAGE_13));
|
||||
CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF));
|
||||
}
|
||||
@ -1766,6 +1782,32 @@ void cDvbTuner::Action(void)
|
||||
}
|
||||
}
|
||||
|
||||
void cDvbTuner::SetPowerSaveMode(bool On)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
if (On) {
|
||||
if (fd_frontend != -1) {
|
||||
dsyslog("closing frontend %d/%d", adapter, frontend);
|
||||
tunerStatus = tsIdle;
|
||||
dvbFrontend->Close();
|
||||
fd_frontend = -1;
|
||||
channel = cChannel();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fd_frontend == -1) {
|
||||
dsyslog("opening frontend %d/%d", adapter, frontend);
|
||||
fd_frontend = dvbFrontend->Open();
|
||||
lastDiseqc = NULL;
|
||||
lastSource = 0;
|
||||
lastUncValue = 0;
|
||||
lastUncDelta = 0;
|
||||
lastUncChange = 0;
|
||||
lnbPowerTurnedOn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- cDvbSourceParam -------------------------------------------------------
|
||||
|
||||
class cDvbSourceParam : public cSourceParam {
|
||||
@ -1856,16 +1898,16 @@ cDvbDevice::cDvbDevice(int Adapter, int Frontend)
|
||||
|
||||
// We only check the devices that must be present - the others will be checked before accessing them://XXX
|
||||
|
||||
dvbTuner = new cDvbTuner(this, adapter, frontend);
|
||||
|
||||
StartSectionHandler();
|
||||
|
||||
dvbTuner = new cDvbTuner(this, adapter, frontend);
|
||||
}
|
||||
|
||||
cDvbDevice::~cDvbDevice()
|
||||
{
|
||||
StopSectionHandler();
|
||||
delete dvbTuner;
|
||||
delete ciAdapter;
|
||||
StopSectionHandler();
|
||||
UnBond();
|
||||
// We're not explicitly closing any device files here, since this sometimes
|
||||
// caused segfaults. Besides, the program is about to terminate anyway...
|
||||
@ -2298,6 +2340,11 @@ bool cDvbDevice::MaySwitchTransponder(const cChannel *Channel) const
|
||||
return BondingOk(Channel, true) && cDevice::MaySwitchTransponder(Channel);
|
||||
}
|
||||
|
||||
void cDvbDevice::SetPowerSaveMode(bool On)
|
||||
{
|
||||
dvbTuner->SetPowerSaveMode(On);
|
||||
}
|
||||
|
||||
bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
||||
{
|
||||
if (dvbTuner->ProvidesFrontend(Channel, true)) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.h 4.7 2020/06/27 10:24:46 kls Exp $
|
||||
* $Id: dvbdevice.h 5.1 2024/07/08 09:34:33 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBDEVICE_H
|
||||
@ -244,6 +244,7 @@ public:
|
||||
virtual const cChannel *GetCurrentlyTunedTransponder(void) const;
|
||||
virtual bool IsTunedToTransponder(const cChannel *Channel) const;
|
||||
virtual bool MaySwitchTransponder(const cChannel *Channel) const;
|
||||
virtual void SetPowerSaveMode(bool On);
|
||||
protected:
|
||||
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
|
||||
public:
|
||||
|
54
dvbplayer.c
54
dvbplayer.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbplayer.c 4.6 2019/05/27 13:54:19 kls Exp $
|
||||
* $Id: dvbplayer.c 5.7 2025/02/19 15:39:16 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbplayer.h"
|
||||
@ -36,7 +36,7 @@ public:
|
||||
bool IsEmpty(void);
|
||||
void Put(uint32_t Pts, int Index, bool Independent);
|
||||
int FindIndex(uint32_t Pts);
|
||||
int FindFrameNumber(uint32_t Pts);
|
||||
int FindFrameNumber(uint32_t Pts, bool Forward);
|
||||
};
|
||||
|
||||
cPtsIndex::cPtsIndex(void)
|
||||
@ -90,30 +90,30 @@ int cPtsIndex::FindIndex(uint32_t Pts)
|
||||
return Index;
|
||||
}
|
||||
|
||||
int cPtsIndex::FindFrameNumber(uint32_t Pts)
|
||||
int cPtsIndex::FindFrameNumber(uint32_t Pts, bool Forward)
|
||||
{
|
||||
if (!Forward)
|
||||
return FindIndex(Pts); // there are only I frames in backward
|
||||
cMutexLock MutexLock(&mutex);
|
||||
if (w == r)
|
||||
return lastFound; // replay always starts at an I frame
|
||||
bool Valid = false;
|
||||
int d;
|
||||
int FrameNumber = 0;
|
||||
int UnplayedIFrame = 2; // GOPs may intersect, so we're looping until we found two unplayed I frames
|
||||
int UnplayedIFrame = 2; // GOPs may intersect, so we loop until we processed a complete unplayed GOP
|
||||
for (int i = r; i != w && UnplayedIFrame; ) {
|
||||
d = Pts - pi[i].pts;
|
||||
if (d > 0x7FFFFFFF)
|
||||
d = 0xFFFFFFFF - d; // handle rollover
|
||||
if (d > 0) {
|
||||
int32_t d = int32_t(Pts - pi[i].pts); // typecast handles rollover
|
||||
if (d >= 0) {
|
||||
if (pi[i].independent) {
|
||||
FrameNumber = pi[i].index; // an I frame's index represents its frame number
|
||||
Valid = true;
|
||||
if (d == 0)
|
||||
UnplayedIFrame = 1; // if Pts is at an I frame we only need to check up to the next I frame
|
||||
}
|
||||
else
|
||||
FrameNumber++; // for every played non-I frame, increase frame number
|
||||
}
|
||||
else
|
||||
if (pi[i].independent)
|
||||
--UnplayedIFrame;
|
||||
else if (pi[i].independent)
|
||||
--UnplayedIFrame;
|
||||
if (++i >= PTSINDEX_ENTRIES)
|
||||
i = 0;
|
||||
}
|
||||
@ -283,6 +283,7 @@ public:
|
||||
void Goto(int Position, bool Still = false);
|
||||
virtual double FramesPerSecond(void) { return framesPerSecond; }
|
||||
virtual void SetAudioTrack(eTrackType Type, const tTrackId *TrackId);
|
||||
virtual const cErrors *GetErrors(void);
|
||||
virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false);
|
||||
virtual bool GetFrameNumber(int &Current, int &Total);
|
||||
virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed);
|
||||
@ -792,15 +793,17 @@ void cDvbPlayer::Forward(void)
|
||||
Pause();
|
||||
break;
|
||||
}
|
||||
Empty();
|
||||
// run into pmPause
|
||||
case pmStill:
|
||||
case pmPause:
|
||||
case pmPause: {
|
||||
LOCK_THREAD;
|
||||
Empty();
|
||||
DeviceMute();
|
||||
playMode = pmSlow;
|
||||
playDir = pdForward;
|
||||
trickSpeed = NORMAL_SPEED;
|
||||
TrickSpeed(Setup.MultiSpeedMode ? -1 : -MAX_SPEEDS);
|
||||
}
|
||||
break;
|
||||
default: esyslog("ERROR: unknown playMode %d (%s)", playMode, __FUNCTION__);
|
||||
}
|
||||
@ -841,7 +844,6 @@ void cDvbPlayer::Backward(void)
|
||||
Pause();
|
||||
break;
|
||||
}
|
||||
Empty();
|
||||
// run into pmPause
|
||||
case pmStill:
|
||||
case pmPause: {
|
||||
@ -914,7 +916,7 @@ void cDvbPlayer::Goto(int Index, bool Still)
|
||||
ptsIndex.Put(isPesRecording ? PesGetPts(b) : TsGetPts(b, r), Index, true);
|
||||
}
|
||||
playMode = pmStill;
|
||||
readIndex = Index;
|
||||
readIndex = Index - 1; // makes sure a later play starts with this I-frame
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -940,6 +942,13 @@ void cDvbPlayer::SetAudioTrack(eTrackType Type, const tTrackId *TrackId)
|
||||
resyncAfterPause = true;
|
||||
}
|
||||
|
||||
const cErrors *cDvbPlayer::GetErrors(void)
|
||||
{
|
||||
if (index)
|
||||
return index->GetErrors();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cDvbPlayer::GetIndex(int &Current, int &Total, bool SnapToIFrame)
|
||||
{
|
||||
if (index) {
|
||||
@ -959,7 +968,7 @@ bool cDvbPlayer::GetIndex(int &Current, int &Total, bool SnapToIFrame)
|
||||
bool cDvbPlayer::GetFrameNumber(int &Current, int &Total)
|
||||
{
|
||||
if (index) {
|
||||
Current = ptsIndex.FindFrameNumber(DeviceGetSTC());
|
||||
Current = ptsIndex.FindFrameNumber(DeviceGetSTC(), playDir == pdForward);
|
||||
Total = index->Last();
|
||||
return true;
|
||||
}
|
||||
@ -981,8 +990,10 @@ bool cDvbPlayer::GetReplayMode(bool &Play, bool &Forward, int &Speed)
|
||||
// --- cDvbPlayerControl -----------------------------------------------------
|
||||
|
||||
cDvbPlayerControl::cDvbPlayerControl(const char *FileName, bool PauseLive)
|
||||
:cControl(player = new cDvbPlayer(FileName, PauseLive))
|
||||
:cControl(NULL)
|
||||
{
|
||||
player = new cDvbPlayer(FileName, PauseLive);
|
||||
SetPlayer(player);
|
||||
}
|
||||
|
||||
cDvbPlayerControl::~cDvbPlayerControl()
|
||||
@ -1045,6 +1056,13 @@ int cDvbPlayerControl::SkipFrames(int Frames)
|
||||
return -1;
|
||||
}
|
||||
|
||||
const cErrors *cDvbPlayerControl::GetErrors(void)
|
||||
{
|
||||
if (player)
|
||||
return player->GetErrors();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cDvbPlayerControl::GetIndex(int &Current, int &Total, bool SnapToIFrame)
|
||||
{
|
||||
if (player) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbplayer.h 4.2 2016/12/22 10:36:50 kls Exp $
|
||||
* $Id: dvbplayer.h 5.1 2024/09/19 09:49:02 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBPLAYER_H
|
||||
@ -47,6 +47,8 @@ public:
|
||||
// The sign of 'Seconds' determines the direction in which to skip.
|
||||
// Use a very large negative value to go all the way back to the
|
||||
// beginning of the recording.
|
||||
const cErrors *GetErrors(void);
|
||||
// Returns the frame indexes of errors in the recording (if any).
|
||||
bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false);
|
||||
// Returns the current and total frame index, optionally snapped to the
|
||||
// nearest I-frame.
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Original author: Marco Schluessler <marco@lordzodiac.de>
|
||||
* With some input from the "subtitles plugin" by Pekka Virtanen <pekka.virtanen@sci.fi>
|
||||
*
|
||||
* $Id: dvbsubtitle.c 5.1 2021/03/17 15:24:34 kls Exp $
|
||||
* $Id: dvbsubtitle.c 5.2 2022/12/06 16:57:01 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbsubtitle.h"
|
||||
@ -1770,11 +1770,13 @@ void cDvbSubtitleConverter::FinishPage(cDvbSubtitlePage *Page)
|
||||
return;
|
||||
int NumAreas;
|
||||
tArea *Areas = Page->GetAreas(NumAreas);
|
||||
if (!Areas)
|
||||
return;
|
||||
tArea AreaCombined = Page->CombineAreas(NumAreas, Areas);
|
||||
tArea AreaOsd = Page->ScaleArea(AreaCombined, osdFactorX, osdFactorY);
|
||||
int Bpp = 8;
|
||||
bool Reduced = false;
|
||||
if (osd && NumAreas > 0) {
|
||||
if (osd) {
|
||||
while (osd->CanHandleAreas(&AreaOsd, 1) != oeOk) {
|
||||
dbgoutput("CanHandleAreas: %d<br>\n", osd->CanHandleAreas(&AreaOsd, 1));
|
||||
int HalfBpp = Bpp / 2;
|
||||
|
27
eit.c
27
eit.c
@ -8,7 +8,7 @@
|
||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||
* Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
|
||||
*
|
||||
* $Id: eit.c 5.2 2021/04/04 11:06:30 kls Exp $
|
||||
* $Id: eit.c 5.6 2022/12/23 09:47:23 kls Exp $
|
||||
*/
|
||||
|
||||
// The various ways in which broadcasters handle (or screw up) their EPG:
|
||||
@ -115,14 +115,6 @@ cEIT::cEIT(cEitTablesHash &EitTablesHash, int Source, u_char Tid, const u_char *
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EpgHandlers.BeginSegmentTransfer(Channel)) {
|
||||
SchedulesStateKey.Remove(false);
|
||||
ChannelsStateKey.Remove(false);
|
||||
return;
|
||||
}
|
||||
|
||||
bool ChannelsModified = false;
|
||||
bool handledExternally = EpgHandlers.HandledExternally(Channel);
|
||||
cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(Channel, true);
|
||||
|
||||
if (pSchedule->OnActualTp(Tid) && (Tid & 0xF0) == 0x60) {
|
||||
@ -131,9 +123,18 @@ cEIT::cEIT(cEitTablesHash &EitTablesHash, int Source, u_char Tid, const u_char *
|
||||
return;
|
||||
}
|
||||
|
||||
if (!EpgHandlers.BeginSegmentTransfer(Channel)) {
|
||||
SchedulesStateKey.Remove(false);
|
||||
ChannelsStateKey.Remove(false);
|
||||
return;
|
||||
}
|
||||
|
||||
bool ChannelsModified = false;
|
||||
bool handledExternally = EpgHandlers.HandledExternally(Channel);
|
||||
|
||||
bool Empty = true;
|
||||
bool Modified = false;
|
||||
time_t LingerLimit = Now - Setup.EPGLinger * 60;
|
||||
time_t LingerLimit = Now - EPG_LINGER_TIME;
|
||||
time_t SegmentStart = 0; // these are actually "section" start/end times
|
||||
time_t SegmentEnd = 0;
|
||||
struct tm t = { 0 };
|
||||
@ -432,9 +433,9 @@ cEIT::cEIT(cEitTablesHash &EitTablesHash, int Source, u_char Tid, const u_char *
|
||||
EpgHandlers.DropOutdated(pSchedule, SegmentStart, SegmentEnd, Tid, getVersionNumber());
|
||||
}
|
||||
}
|
||||
EpgHandlers.EndSegmentTransfer(Modified);
|
||||
SchedulesStateKey.Remove(Modified);
|
||||
ChannelsStateKey.Remove(ChannelsModified);
|
||||
EpgHandlers.EndSegmentTransfer(Modified);
|
||||
}
|
||||
|
||||
// --- cTDT ------------------------------------------------------------------
|
||||
@ -469,7 +470,7 @@ cTDT::cTDT(const u_char *Data)
|
||||
timespec ts = {};
|
||||
ts.tv_sec = dvbtim;
|
||||
if (clock_settime(CLOCK_REALTIME, &ts) == 0)
|
||||
isyslog("system time changed from %s (%ld) to %s (%ld)", *TimeToString(loctim), loctim, *TimeToString(dvbtim), dvbtim);
|
||||
isyslog("system time changed from %s (%jd) to %s (%jd)", *TimeToString(loctim), intmax_t(loctim), *TimeToString(dvbtim), intmax_t(dvbtim));
|
||||
else
|
||||
esyslog("ERROR while setting system time: %m");
|
||||
}
|
||||
@ -479,7 +480,7 @@ cTDT::cTDT(const u_char *Data)
|
||||
delta.tv_sec = diff;
|
||||
delta.tv_usec = 0;
|
||||
if (adjtime(&delta, NULL) == 0)
|
||||
isyslog("system time adjustment initiated from %s (%ld) to %s (%ld)", *TimeToString(loctim), loctim, *TimeToString(dvbtim), dvbtim);
|
||||
isyslog("system time adjustment initiated from %s (%jd) to %s (%jd)", *TimeToString(loctim), intmax_t(loctim), *TimeToString(dvbtim), intmax_t(dvbtim));
|
||||
else
|
||||
esyslog("ERROR while adjusting system time: %m");
|
||||
}
|
||||
|
62
eitscan.c
62
eitscan.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: eitscan.c 4.3 2019/03/12 11:46:05 kls Exp $
|
||||
* $Id: eitscan.c 5.7 2024/07/13 20:12:24 kls Exp $
|
||||
*/
|
||||
|
||||
#include "eitscan.h"
|
||||
@ -44,11 +44,23 @@ int cScanData::Compare(const cListObject &ListObject) const
|
||||
// --- cScanList -------------------------------------------------------------
|
||||
|
||||
class cScanList : public cList<cScanData> {
|
||||
private:
|
||||
bool HasDeviceForChannelEIT(const cChannel *Channel) const;
|
||||
public:
|
||||
void AddTransponders(const cList<cChannel> *Channels);
|
||||
void AddTransponder(const cChannel *Channel);
|
||||
};
|
||||
|
||||
bool cScanList::HasDeviceForChannelEIT(const cChannel *Channel) const
|
||||
{
|
||||
for (int i = 0; i < cDevice::NumDevices(); i++) {
|
||||
cDevice *Device = cDevice::GetDevice(i);
|
||||
if (Device && Device->ProvidesEIT() && Device->ProvidesTransponder(Channel))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cScanList::AddTransponders(const cList<cChannel> *Channels)
|
||||
{
|
||||
for (const cChannel *ch = Channels->First(); ch; ch = Channels->Next(ch))
|
||||
@ -58,7 +70,9 @@ void cScanList::AddTransponders(const cList<cChannel> *Channels)
|
||||
|
||||
void cScanList::AddTransponder(const cChannel *Channel)
|
||||
{
|
||||
if (Channel->Source() && Channel->Transponder()) {
|
||||
if (Channel->Source() && Channel->Transponder() && (Setup.EPGScanMaxChannel <= 0 || Channel->Number() < Setup.EPGScanMaxChannel)) {
|
||||
if (!HasDeviceForChannelEIT(Channel))
|
||||
return;
|
||||
for (cScanData *sd = First(); sd; sd = Next(sd)) {
|
||||
if (sd->Source() == Channel->Source() && ISTRANSPONDER(sd->Transponder(), Channel->Transponder()))
|
||||
return;
|
||||
@ -91,9 +105,11 @@ cEITScanner EITScanner;
|
||||
|
||||
cEITScanner::cEITScanner(void)
|
||||
{
|
||||
lastScan = lastActivity = time(NULL);
|
||||
paused = false;
|
||||
lastScan = 0;
|
||||
lastActivity = time(NULL);
|
||||
currentChannel = 0;
|
||||
scanList = NULL;
|
||||
scanList = new cScanList;
|
||||
transponderList = NULL;
|
||||
}
|
||||
|
||||
@ -130,25 +146,46 @@ void cEITScanner::Process(void)
|
||||
if (Setup.EPGScanTimeout || !lastActivity) { // !lastActivity means a scan was forced
|
||||
time_t now = time(NULL);
|
||||
if (now - lastScan > ScanTimeout && now - lastActivity > ActivityTimeout) {
|
||||
if (Setup.EPGPauseAfterScan && scanList->Count() == 0 && lastActivity && lastScan && now - lastScan < Setup.EPGScanTimeout * 3600) {
|
||||
if (!paused) {
|
||||
dsyslog("pause EPG scan");
|
||||
paused = true;
|
||||
}
|
||||
// Allow unused devices to go into power save mode:
|
||||
if ((now - lastScan) % 10 == 0) { // let's not do this too often
|
||||
for (int i = 0; i < cDevice::NumDevices(); i++) {
|
||||
if (cDevice *Device = cDevice::GetDevice(i))
|
||||
Device->SetPowerSaveIfUnused();
|
||||
}
|
||||
}
|
||||
return; // pause for Setup.EPGScanTimeout hours
|
||||
}
|
||||
else if (paused) {
|
||||
dsyslog("start EPG scan");
|
||||
paused = false;
|
||||
}
|
||||
cStateKey StateKey;
|
||||
if (const cChannels *Channels = cChannels::GetChannelsRead(StateKey, 10)) {
|
||||
if (!scanList) {
|
||||
scanList = new cScanList;
|
||||
if (scanList->Count() == 0) {
|
||||
if (transponderList) {
|
||||
scanList->AddTransponders(transponderList);
|
||||
delete transponderList;
|
||||
transponderList = NULL;
|
||||
}
|
||||
scanList->AddTransponders(Channels);
|
||||
//dsyslog("EIT scan: %d scanList entries", scanList->Count());
|
||||
}
|
||||
bool AnyDeviceSwitched = false;
|
||||
for (int i = 0; i < cDevice::NumDevices(); i++) {
|
||||
cDevice *Device = cDevice::GetDevice(i);
|
||||
if (Device && Device->ProvidesEIT()) {
|
||||
for (cScanData *ScanData = scanList->First(); ScanData; ScanData = scanList->Next(ScanData)) {
|
||||
cScanData *Next = NULL;
|
||||
for (cScanData *ScanData = scanList->First(); ScanData; ScanData = Next) {
|
||||
Next = scanList->Next(ScanData);
|
||||
const cChannel *Channel = ScanData->GetChannel();
|
||||
if (Channel) {
|
||||
if (!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= CA_ENCRYPTED_MIN) {
|
||||
if (Device->IsTunedToTransponder(Channel))
|
||||
scanList->Del(ScanData);
|
||||
else if (!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= CA_ENCRYPTED_MIN) {
|
||||
if (Device->ProvidesTransponder(Channel)) {
|
||||
if (Device->Priority() < 0) {
|
||||
if (const cPositioner *Positioner = Device->Positioner()) {
|
||||
@ -164,10 +201,9 @@ void cEITScanner::Process(void)
|
||||
Skins.Message(mtInfo, tr("Starting EPG scan"));
|
||||
}
|
||||
}
|
||||
//dsyslog("EIT scan: device %d source %-8s tp %5d", Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder());
|
||||
//dsyslog("EIT scan: %d device %d source %-8s tp %5d", scanList->Count(), Device->DeviceNumber() + 1, *cSource::ToString(Channel->Source()), Channel->Transponder());
|
||||
Device->SwitchChannel(Channel, false);
|
||||
scanList->Del(ScanData);
|
||||
AnyDeviceSwitched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -177,9 +213,7 @@ void cEITScanner::Process(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!AnyDeviceSwitched) {
|
||||
delete scanList;
|
||||
scanList = NULL;
|
||||
if (scanList->Count() == 0) {
|
||||
if (lastActivity == 0) // this was a triggered scan
|
||||
Activity();
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: eitscan.h 2.1 2012/03/07 14:16:57 kls Exp $
|
||||
* $Id: eitscan.h 5.1 2024/07/06 11:19:21 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __EITSCAN_H
|
||||
@ -23,6 +23,7 @@ private:
|
||||
enum { ActivityTimeout = 60,
|
||||
ScanTimeout = 20
|
||||
};
|
||||
bool paused;
|
||||
time_t lastScan, lastActivity;
|
||||
int currentChannel;
|
||||
cScanList *scanList;
|
||||
|
103
epg.c
103
epg.c
@ -7,7 +7,7 @@
|
||||
* Original version (as used in VDR before 1.3.0) written by
|
||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||
*
|
||||
* $Id: epg.c 5.3 2021/04/06 09:01:26 kls Exp $
|
||||
* $Id: epg.c 5.13 2024/11/30 14:30:46 kls Exp $
|
||||
*/
|
||||
|
||||
#include "epg.h"
|
||||
@ -145,7 +145,10 @@ cEvent::~cEvent()
|
||||
int cEvent::Compare(const cListObject &ListObject) const
|
||||
{
|
||||
cEvent *e = (cEvent *)&ListObject;
|
||||
return startTime - e->startTime;
|
||||
int d = startTime - e->startTime;
|
||||
if (d == 0)
|
||||
d = int(tableID) - int(e->tableID);
|
||||
return d;
|
||||
}
|
||||
|
||||
tChannelID cEvent::ChannelID(void) const
|
||||
@ -177,7 +180,7 @@ void cEvent::SetVersion(uchar Version)
|
||||
void cEvent::SetRunningStatus(int RunningStatus, const cChannel *Channel)
|
||||
{
|
||||
if (Channel && runningStatus != RunningStatus && (RunningStatus > SI::RunningStatusNotRunning || runningStatus > SI::RunningStatusUndefined) && schedule && schedule->HasTimer())
|
||||
isyslog("channel %d (%s) event %s status %d", Channel->Number(), Channel->Name(), *ToDescr(), RunningStatus);
|
||||
isyslog("channel %d (%s) event %s status %d->%d", Channel->Number(), Channel->Name(), *ToDescr(), runningStatus, RunningStatus);
|
||||
runningStatus = RunningStatus;
|
||||
}
|
||||
|
||||
@ -300,7 +303,7 @@ const char *cEvent::ContentToString(uchar Content)
|
||||
case 0x01: return tr("Content$News/Weather Report");
|
||||
case 0x02: return tr("Content$News Magazine");
|
||||
case 0x03: return tr("Content$Documentary");
|
||||
case 0x04: return tr("Content$Discussion/Inverview/Debate");
|
||||
case 0x04: return tr("Content$Discussion/Interview/Debate");
|
||||
}
|
||||
break;
|
||||
case ecgShow:
|
||||
@ -346,7 +349,7 @@ const char *cEvent::ContentToString(uchar Content)
|
||||
case 0x00: return tr("Content$Music/Ballet/Dance");
|
||||
case 0x01: return tr("Content$Rock/Pop");
|
||||
case 0x02: return tr("Content$Serious/Classical Music");
|
||||
case 0x03: return tr("Content$Folk/Tradional Music");
|
||||
case 0x03: return tr("Content$Folk/Traditional Music");
|
||||
case 0x04: return tr("Content$Jazz");
|
||||
case 0x05: return tr("Content$Musical/Opera");
|
||||
case 0x06: return tr("Content$Ballet");
|
||||
@ -450,8 +453,8 @@ cString cEvent::GetVpsString(void) const
|
||||
|
||||
void cEvent::Dump(FILE *f, const char *Prefix, bool InfoOnly) const
|
||||
{
|
||||
if (InfoOnly || startTime + duration + Setup.EPGLinger * 60 >= time(NULL)) {
|
||||
fprintf(f, "%sE %u %ld %d %X %X\n", Prefix, eventID, startTime, duration, tableID, version);
|
||||
if (InfoOnly || startTime + duration + EPG_LINGER_TIME >= time(NULL)) {
|
||||
fprintf(f, "%sE %u %jd %d %X %X\n", Prefix, eventID, intmax_t(startTime), duration, tableID, version);
|
||||
if (!isempty(title))
|
||||
fprintf(f, "%sT %s\n", Prefix, title);
|
||||
if (!isempty(shortText))
|
||||
@ -476,7 +479,7 @@ void cEvent::Dump(FILE *f, const char *Prefix, bool InfoOnly) const
|
||||
}
|
||||
}
|
||||
if (vps)
|
||||
fprintf(f, "%sV %ld\n", Prefix, vps);
|
||||
fprintf(f, "%sV %jd\n", Prefix, intmax_t(vps));
|
||||
if (!InfoOnly && !isempty(aux)) {
|
||||
strreplace(aux, '\n', '|');
|
||||
fprintf(f, "%s@ %s\n", Prefix, aux);
|
||||
@ -518,7 +521,7 @@ bool cEvent::Parse(char *s)
|
||||
components = new cComponents;
|
||||
components->SetComponent(components->NumComponents(), t);
|
||||
break;
|
||||
case 'V': SetVps(atoi(t));
|
||||
case 'V': SetVps(atol(t));
|
||||
break;
|
||||
case '@': strreplace(t, '|', '\n');
|
||||
SetAux(t);
|
||||
@ -541,11 +544,11 @@ bool cEvent::Read(FILE *f, cSchedule *Schedule, int &Line)
|
||||
switch (*s) {
|
||||
case 'E': if (!Event) {
|
||||
unsigned int EventID;
|
||||
time_t StartTime;
|
||||
intmax_t StartTime; // actually time_t, but intmax_t for scanning with "%jd"
|
||||
int Duration;
|
||||
unsigned int TableID = 0;
|
||||
unsigned int Version = 0xFF; // actual value is ignored
|
||||
int n = sscanf(t, "%u %ld %d %X %X", &EventID, &StartTime, &Duration, &TableID, &Version);
|
||||
int n = sscanf(t, "%u %jd %d %X %X", &EventID, &StartTime, &Duration, &TableID, &Version);
|
||||
if (n >= 3 && n <= 5) {
|
||||
Event = (cEvent *)Schedule->GetEventByTime(StartTime);
|
||||
cEvent *newEvent = NULL;
|
||||
@ -885,6 +888,23 @@ void cEvent::FixEpgBugs(void)
|
||||
|
||||
Final:
|
||||
|
||||
// And then there are the specially gifted people who put a literal "\n" string where there should be
|
||||
// a '\n' character:
|
||||
if (shortText) {
|
||||
if (char *p = strstr(shortText, "\\n")) {
|
||||
*p = 0;
|
||||
p += 2;
|
||||
char *s = strdup(shortText);
|
||||
char *d = strdup(cString::sprintf("%s\n\n%s", p, description));
|
||||
free(shortText);
|
||||
free(description);
|
||||
shortText = s;
|
||||
description = d;
|
||||
EpgBugFixStat(12, ChannelID());
|
||||
}
|
||||
}
|
||||
description = strreplace(description, "\\n", " \n");
|
||||
|
||||
// VDR can't usefully handle newline characters in the title, shortText or component description of EPG
|
||||
// data, so let's always convert them to blanks (independent of the setting of EPGBugfixLevel):
|
||||
strreplace(title, '\n', ' ');
|
||||
@ -911,7 +931,6 @@ cSchedule::cSchedule(tChannelID ChannelID)
|
||||
channelID = ChannelID;
|
||||
events.SetUseGarbageCollector();
|
||||
numTimers = 0;
|
||||
hasRunning = false;
|
||||
modified = 0;
|
||||
onActualTp = false;
|
||||
presentSeen = 0;
|
||||
@ -1011,18 +1030,6 @@ const cEvent *cSchedule::GetFollowingEvent(void) const
|
||||
return p;
|
||||
}
|
||||
|
||||
#if DEPRECATED_SCHEDULE_GET_EVENT
|
||||
const cEvent *cSchedule::GetEvent(tEventID EventID, time_t StartTime) const
|
||||
{
|
||||
// Returns the event info with the given StartTime or, if no actual StartTime
|
||||
// is given, the one with the given EventID.
|
||||
if (StartTime > 0) // 'StartTime < 0' is apparently used with NVOD channels
|
||||
return eventsHashStartTime.Get(StartTime);
|
||||
else
|
||||
return eventsHashID.Get(EventID);
|
||||
}
|
||||
#endif
|
||||
|
||||
const cEvent *cSchedule::GetEventById(tEventID EventID) const
|
||||
{
|
||||
return eventsHashID.Get(EventID);
|
||||
@ -1051,7 +1058,6 @@ const cEvent *cSchedule::GetEventAround(time_t Time) const
|
||||
|
||||
void cSchedule::SetRunningStatus(cEvent *Event, int RunningStatus, const cChannel *Channel)
|
||||
{
|
||||
hasRunning = false;
|
||||
for (cEvent *p = events.First(); p; p = events.Next(p)) {
|
||||
if (p == Event) {
|
||||
if (p->RunningStatus() > SI::RunningStatusNotRunning || RunningStatus > SI::RunningStatusNotRunning) {
|
||||
@ -1061,24 +1067,19 @@ void cSchedule::SetRunningStatus(cEvent *Event, int RunningStatus, const cChanne
|
||||
}
|
||||
else if (RunningStatus >= SI::RunningStatusPausing && p->StartTime() < Event->StartTime())
|
||||
p->SetRunningStatus(SI::RunningStatusNotRunning, Channel);
|
||||
if (p->RunningStatus() >= SI::RunningStatusPausing)
|
||||
hasRunning = true;
|
||||
}
|
||||
SetPresentSeen();
|
||||
}
|
||||
|
||||
void cSchedule::ClrRunningStatus(cChannel *Channel)
|
||||
{
|
||||
if (hasRunning) {
|
||||
for (cEvent *p = events.First(); p; p = events.Next(p)) {
|
||||
if (p->RunningStatus() >= SI::RunningStatusPausing) {
|
||||
p->SetRunningStatus(SI::RunningStatusNotRunning, Channel);
|
||||
hasRunning = false;
|
||||
SetModified();
|
||||
break;
|
||||
}
|
||||
for (cEvent *p = events.First(); p; p = events.Next(p)) {
|
||||
if (p->RunningStatus() >= SI::RunningStatusPausing) {
|
||||
p->SetRunningStatus(SI::RunningStatusNotRunning, Channel);
|
||||
SetModified();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cSchedule::ResetVersions(void)
|
||||
@ -1090,14 +1091,6 @@ void cSchedule::ResetVersions(void)
|
||||
void cSchedule::Sort(void)
|
||||
{
|
||||
events.Sort();
|
||||
// Make sure there are no RunningStatusUndefined before the currently running event:
|
||||
if (hasRunning) {
|
||||
for (cEvent *p = events.First(); p; p = events.Next(p)) {
|
||||
if (p->RunningStatus() >= SI::RunningStatusPausing)
|
||||
break;
|
||||
p->SetRunningStatus(SI::RunningStatusNotRunning);
|
||||
}
|
||||
}
|
||||
SetModified();
|
||||
}
|
||||
|
||||
@ -1118,12 +1111,26 @@ void cSchedule::DropOutdated(time_t SegmentStart, time_t SegmentEnd, uchar Table
|
||||
DelEvent(p);
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
p = n;
|
||||
}
|
||||
}
|
||||
// Make sure there are no two events with the same start time:
|
||||
for (cEvent *p = events.First(); p; p = events.Next(p)) {
|
||||
cEvent *n = events.Next(p);
|
||||
if (n && n->StartTime() == p->StartTime())
|
||||
DelEvent(n);
|
||||
}
|
||||
// Make sure there are no RunningStatusUndefined before the currently running event:
|
||||
for (cEvent *p = events.First(); p; p = events.Next(p)) {
|
||||
if (p->RunningStatus() >= SI::RunningStatusPausing) {
|
||||
for (p = events.Prev(p); p; p = events.Prev(p))
|
||||
p->SetRunningStatus(SI::RunningStatusNotRunning);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cSchedule::Cleanup(void)
|
||||
@ -1135,7 +1142,7 @@ void cSchedule::Cleanup(time_t Time)
|
||||
{
|
||||
cEvent *Event;
|
||||
while ((Event = events.First()) != NULL) {
|
||||
if (!Event->HasTimer() && Event->EndTime() + Setup.EPGLinger * 60 < Time)
|
||||
if (!Event->HasTimer() && Event->EndTime() + EPG_LINGER_TIME < Time)
|
||||
DelEvent(Event);
|
||||
else
|
||||
break;
|
||||
@ -1385,6 +1392,8 @@ const cSchedule *cSchedules::GetSchedule(const cChannel *Channel, bool AddIfMiss
|
||||
{
|
||||
// This is not very beautiful, but it dramatically speeds up the
|
||||
// "What's on now/next?" menus.
|
||||
if (!Channel)
|
||||
return NULL;
|
||||
static cSchedule DummySchedule(tChannelID::InvalidID);
|
||||
if (!Channel->schedule)
|
||||
Channel->schedule = GetSchedule(Channel->GetChannelID());
|
||||
|
12
epg.h
12
epg.h
@ -7,7 +7,7 @@
|
||||
* Original version (as used in VDR before 1.3.0) written by
|
||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||
*
|
||||
* $Id: epg.h 5.1 2021/04/04 11:06:30 kls Exp $
|
||||
* $Id: epg.h 5.8 2024/10/13 09:47:18 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __EPG_H
|
||||
@ -20,6 +20,8 @@
|
||||
|
||||
#define MAXEPGBUGFIXLEVEL 3
|
||||
|
||||
#define EPG_LINGER_TIME (max(Setup.EPGLinger, 180) * 60) // seconds to keep old EPG data (internal, must be at least Setup.EPGLinger)
|
||||
|
||||
enum { MaxEventContents = 4 };
|
||||
|
||||
enum eEventContentGroup {
|
||||
@ -155,7 +157,6 @@ private:
|
||||
cHash<cEvent> eventsHashID;
|
||||
cHash<cEvent> eventsHashStartTime;
|
||||
mutable u_int16_t numTimers;// The number of timers that use this schedule
|
||||
bool hasRunning;
|
||||
bool onActualTp;
|
||||
int modified;
|
||||
time_t presentSeen;
|
||||
@ -185,10 +186,6 @@ public:
|
||||
const cList<cEvent> *Events(void) const { return &events; }
|
||||
const cEvent *GetPresentEvent(void) const;
|
||||
const cEvent *GetFollowingEvent(void) const;
|
||||
#define DEPRECATED_SCHEDULE_GET_EVENT 1
|
||||
#if DEPRECATED_SCHEDULE_GET_EVENT
|
||||
const cEvent *GetEvent(tEventID EventID, time_t StartTime = 0) const;
|
||||
#endif
|
||||
const cEvent *GetEventById(tEventID EventID) const;
|
||||
const cEvent *GetEventByTime(time_t StartTime) const;
|
||||
const cEvent *GetEventAround(time_t Time) const;
|
||||
@ -272,6 +269,7 @@ public:
|
||||
///< therefore the EPG handlers have to take care of this. Otherwise the parsing of
|
||||
///< non-updates will waste a lot of resources.
|
||||
virtual bool SetEventID(cEvent *Event, tEventID EventID) { return false; }
|
||||
///< Important note: if you want VPS to work, do not mess with the event ids!
|
||||
virtual bool SetTitle(cEvent *Event, const char *Title) { return false; }
|
||||
virtual bool SetShortText(cEvent *Event, const char *ShortText) { return false; }
|
||||
virtual bool SetDescription(cEvent *Event, const char *Description) { return false; }
|
||||
@ -296,7 +294,7 @@ public:
|
||||
///< Designed to give handlers the possibility to prepare a database transaction.
|
||||
///< If any EPG handler returns false in this function, it is assumed that
|
||||
///< the EPG for the given Channel has to be handled later due to some transaction problems,
|
||||
///> therefore the processing will aborted.
|
||||
///> therefore the processing will be aborted.
|
||||
///< Dummy is for backward compatibility and may be removed in a future version.
|
||||
virtual bool EndSegmentTransfer(bool Modified, bool Dummy) { return false; } // TODO remove obsolete Dummy
|
||||
///< Called after the segment data has been processed.
|
||||
|
31
filter.c
31
filter.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: filter.c 5.1 2021/03/16 15:10:54 kls Exp $
|
||||
* $Id: filter.c 5.2 2024/10/13 09:47:18 kls Exp $
|
||||
*/
|
||||
|
||||
#include "filter.h"
|
||||
@ -73,35 +73,6 @@ bool cSectionSyncer::Processed(int SectionNumber, int LastSectionNumber, int Seg
|
||||
return complete;
|
||||
}
|
||||
|
||||
#if DEPRECATED_SECTIONSYNCER_SYNC_REPEAT
|
||||
void cSectionSyncer::Repeat(void)
|
||||
{
|
||||
SetSectionFlag(currentSection, false);
|
||||
synced = false;
|
||||
complete = false;
|
||||
}
|
||||
|
||||
bool cSectionSyncer::Sync(uchar Version, int Number, int LastNumber)
|
||||
{
|
||||
if (Version != currentVersion) {
|
||||
Reset();
|
||||
currentVersion = Version;
|
||||
}
|
||||
if (!synced) {
|
||||
if (Number != 0)
|
||||
return false;
|
||||
else
|
||||
synced = true;
|
||||
}
|
||||
currentSection = Number;
|
||||
bool Result = !GetSectionFlag(Number);
|
||||
SetSectionFlag(Number, true);
|
||||
if (Number == LastNumber)
|
||||
complete = true;
|
||||
return Result;
|
||||
}
|
||||
#endif
|
||||
|
||||
// --- cFilterData -----------------------------------------------------------
|
||||
|
||||
cFilterData::cFilterData(void)
|
||||
|
8
filter.h
8
filter.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: filter.h 5.1 2021/03/16 15:10:54 kls Exp $
|
||||
* $Id: filter.h 5.5 2024/10/13 09:47:18 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __FILTER_H
|
||||
@ -13,8 +13,6 @@
|
||||
#include <sys/types.h>
|
||||
#include "tools.h"
|
||||
|
||||
#define DEPRECATED_SECTIONSYNCER_SYNC_REPEAT 1
|
||||
|
||||
class cSectionSyncer {
|
||||
private:
|
||||
int currentVersion;
|
||||
@ -49,10 +47,6 @@ public:
|
||||
///< Returns true if all sections have been processed.
|
||||
bool Complete(void) { return complete; }
|
||||
///< Returns true if all sections have been processed.
|
||||
#if DEPRECATED_SECTIONSYNCER_SYNC_REPEAT
|
||||
void Repeat(void);
|
||||
bool Sync(uchar Version, int Number, int LastNumber);
|
||||
#endif
|
||||
};
|
||||
|
||||
class cSectionSyncerRandom : public cSectionSyncer {
|
||||
|
11
font.c
11
font.c
@ -6,7 +6,7 @@
|
||||
*
|
||||
* BiDi support by Osama Alrawab <alrawab@hotmail.com> @2008 Tripoli-Libya.
|
||||
*
|
||||
* $Id: font.c 4.2 2016/12/22 12:31:23 kls Exp $
|
||||
* $Id: font.c 5.3 2025/02/17 11:13:13 kls Exp $
|
||||
*/
|
||||
|
||||
#include "font.h"
|
||||
@ -74,7 +74,8 @@ cGlyph::cGlyph(uint CharCode, FT_GlyphSlotRec_ *GlyphData)
|
||||
rows = GlyphData->bitmap.rows;
|
||||
pitch = GlyphData->bitmap.pitch;
|
||||
bitmap = MALLOC(uchar, rows * pitch);
|
||||
memcpy(bitmap, GlyphData->bitmap.buffer, rows * pitch);
|
||||
if (int bytes = rows * pitch)
|
||||
memcpy(bitmap, GlyphData->bitmap.buffer, bytes);
|
||||
}
|
||||
|
||||
cGlyph::~cGlyph()
|
||||
@ -429,8 +430,10 @@ cFont *cFont::CreateFont(const char *Name, int CharHeight, int CharWidth)
|
||||
{
|
||||
cString fn = GetFontFileName(Name);
|
||||
cFont *f = *fn ? new cFreetypeFont(fn, CharHeight, CharWidth) : NULL;
|
||||
if (!f || !f->Height())
|
||||
if (!f || !f->Height()) {
|
||||
delete f;
|
||||
f = new cDummyFont(CharHeight, CharWidth);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
@ -615,7 +618,7 @@ void cTextWrapper::Set(const char *Text, const cFont *Font, int Width)
|
||||
}
|
||||
}
|
||||
w += cw;
|
||||
if (strchr("-.,:;!?_", *p)) {
|
||||
if (strchr("-.,:;!?_~", *p)) {
|
||||
Delim = p;
|
||||
Blank = NULL;
|
||||
}
|
||||
|
4
i18n.c
4
i18n.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: i18n.c 4.2 2020/06/15 15:57:32 kls Exp $
|
||||
* $Id: i18n.c 5.2 2022/12/01 20:57:12 kls Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -80,6 +80,8 @@ const char *LanguageCodeList[] = {
|
||||
struct tSpecialLc { const char *Code; const char *Name; };
|
||||
const struct tSpecialLc SpecialLanguageCodeList[] = {
|
||||
{ "qaa", trNOOP("LanguageName$original language (qaa)") },
|
||||
{ "qad", trNOOP("LanguageName$audio description (qad)") },
|
||||
{ "qks", trNOOP("LanguageName$clear speech (qks)") },
|
||||
{ "mis", trNOOP("LanguageName$uncoded languages (mis)") },
|
||||
{ "mul", trNOOP("LanguageName$multiple languages (mul)") },
|
||||
{ "nar", trNOOP("LanguageName$narrative (nar)") },
|
||||
|
@ -6,7 +6,7 @@
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* $Id: si.h 4.3 2020/05/15 12:32:51 kls Exp $
|
||||
* $Id: si.h 5.1 2023/02/16 17:20:09 kls Exp $
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
@ -47,7 +47,6 @@ enum TableId { TableIdPAT = 0x00, //program association section
|
||||
TableIdPremiereCIT = 0xA0 //premiere content information section
|
||||
};
|
||||
|
||||
|
||||
enum DescriptorTag {
|
||||
// defined by ISO/IEC 13818-1
|
||||
VideoStreamDescriptorTag = 0x02,
|
||||
|
@ -6,7 +6,7 @@
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* $Id: util.c 1.7 2006/02/18 11:17:50 kls Exp $
|
||||
* $Id: util.c 5.1 2021/05/19 11:55:00 kls Exp $
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
@ -266,7 +266,7 @@ u_int32_t CRC32::crc_table[256] = {
|
||||
|
||||
u_int32_t CRC32::crc32 (const char *d, int len, u_int32_t crc)
|
||||
{
|
||||
register int i;
|
||||
int i;
|
||||
const unsigned char *u=(unsigned char*)d; // Saves '& 0xff'
|
||||
|
||||
for (i=0; i<len; i++)
|
||||
|
@ -6,7 +6,7 @@
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* $Id: util.h 2.3 2012/02/26 13:58:26 kls Exp $
|
||||
* $Id: util.h 5.1 2023/02/16 17:20:09 kls Exp $
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
@ -121,8 +121,6 @@ private:
|
||||
int off;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//abstract base class
|
||||
class Parsable {
|
||||
public:
|
||||
|
150
lirc.c
150
lirc.c
@ -6,24 +6,50 @@
|
||||
*
|
||||
* LIRC support added by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16.
|
||||
*
|
||||
* $Id: lirc.c 4.2 2020/09/16 13:48:33 kls Exp $
|
||||
* $Id: lirc.c 5.2 2023/02/16 17:15:06 kls Exp $
|
||||
*/
|
||||
|
||||
#include "lirc.h"
|
||||
#include <linux/version.h>
|
||||
#define HAVE_KERNEL_LIRC (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
|
||||
// cLircUsrRemote
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
// cLircDevRemote
|
||||
#if HAVE_KERNEL_LIRC
|
||||
#include <linux/lirc.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif
|
||||
|
||||
#define RECONNECTDELAY 3000 // ms
|
||||
|
||||
cLircRemote::cLircRemote(const char *DeviceName)
|
||||
:cRemote("LIRC")
|
||||
class cLircUsrRemote : public cLircRemote {
|
||||
private:
|
||||
enum { LIRC_KEY_BUF = 30, LIRC_BUFFER_SIZE = 128 };
|
||||
struct sockaddr_un addr;
|
||||
bool Connect(void);
|
||||
virtual void Action(void);
|
||||
public:
|
||||
cLircUsrRemote(const char *DeviceName);
|
||||
};
|
||||
|
||||
#if HAVE_KERNEL_LIRC
|
||||
class cLircDevRemote : public cLircRemote {
|
||||
private:
|
||||
virtual void Action(void);
|
||||
public:
|
||||
cLircDevRemote(void);
|
||||
bool Connect(const char *DeviceName);
|
||||
};
|
||||
#endif
|
||||
|
||||
// --- cLircRemote -----------------------------------------------------------
|
||||
|
||||
cLircRemote::cLircRemote(const char *Name)
|
||||
:cRemote(Name)
|
||||
,cThread("LIRC remote control")
|
||||
{
|
||||
addr.sun_family = AF_UNIX;
|
||||
strn0cpy(addr.sun_path, DeviceName, sizeof(addr.sun_path));
|
||||
if (!Connect())
|
||||
f = -1;
|
||||
Start();
|
||||
}
|
||||
|
||||
cLircRemote::~cLircRemote()
|
||||
@ -35,7 +61,28 @@ cLircRemote::~cLircRemote()
|
||||
close(fh);
|
||||
}
|
||||
|
||||
bool cLircRemote::Connect(void)
|
||||
void cLircRemote::NewLircRemote(const char *Name)
|
||||
{
|
||||
#if HAVE_KERNEL_LIRC
|
||||
cLircDevRemote *r = new cLircDevRemote();
|
||||
if (r->Connect(Name))
|
||||
return;
|
||||
delete r;
|
||||
#endif
|
||||
new cLircUsrRemote(Name);
|
||||
}
|
||||
// --- cLircUsrRemote --------------------------------------------------------
|
||||
|
||||
cLircUsrRemote::cLircUsrRemote(const char *DeviceName)
|
||||
: cLircRemote("LIRC")
|
||||
{
|
||||
addr.sun_family = AF_UNIX;
|
||||
strn0cpy(addr.sun_path, DeviceName, sizeof(addr.sun_path));
|
||||
Connect();
|
||||
Start();
|
||||
}
|
||||
|
||||
bool cLircUsrRemote::Connect(void)
|
||||
{
|
||||
if ((f = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
|
||||
if (connect(f, (struct sockaddr *)&addr, sizeof(addr)) >= 0)
|
||||
@ -54,7 +101,7 @@ bool cLircRemote::Ready(void)
|
||||
return f >= 0;
|
||||
}
|
||||
|
||||
void cLircRemote::Action(void)
|
||||
void cLircUsrRemote::Action(void)
|
||||
{
|
||||
cTimeMs FirstTime;
|
||||
cTimeMs LastTime;
|
||||
@ -129,3 +176,86 @@ void cLircRemote::Action(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- cLircDevRemote --------------------------------------------------------
|
||||
|
||||
#if HAVE_KERNEL_LIRC
|
||||
bool cLircDevRemote::Connect(const char *DeviceName)
|
||||
{
|
||||
unsigned mode = LIRC_MODE_SCANCODE;
|
||||
f = open(DeviceName, O_RDONLY, 0);
|
||||
if (f < 0) {
|
||||
switch (errno) {
|
||||
case ENXIO:
|
||||
case ENODEV:
|
||||
// Do not complain about an attempt to open a lircd socket file.
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR_STR(DeviceName);
|
||||
}
|
||||
}
|
||||
else if (ioctl(f, LIRC_SET_REC_MODE, &mode)) {
|
||||
LOG_ERROR_STR(DeviceName);
|
||||
close(f);
|
||||
f = -1;
|
||||
}
|
||||
if (f >= 0)
|
||||
Start();
|
||||
return f >= 0;
|
||||
}
|
||||
|
||||
cLircDevRemote::cLircDevRemote(void)
|
||||
:cLircRemote("DEV_LIRC")
|
||||
{
|
||||
}
|
||||
|
||||
void cLircDevRemote::Action(void)
|
||||
{
|
||||
if (f < 0)
|
||||
return;
|
||||
uint64_t FirstTime = 0, LastTime = 0;
|
||||
uint32_t LastKeyCode = 0;
|
||||
uint16_t LastFlags = false;
|
||||
bool SeenRepeat = false;
|
||||
bool repeat = false;
|
||||
|
||||
while (Running()) {
|
||||
lirc_scancode sc;
|
||||
ssize_t ret = read(f, &sc, sizeof sc);
|
||||
|
||||
if (ret == sizeof sc) {
|
||||
const bool SameKey = sc.keycode == LastKeyCode && !((sc.flags ^ LastFlags) & LIRC_SCANCODE_FLAG_TOGGLE);
|
||||
|
||||
if (sc.flags & LIRC_SCANCODE_FLAG_REPEAT != 0)
|
||||
// Before Linux 6.0, this flag is never set for some devices.
|
||||
SeenRepeat = true;
|
||||
|
||||
if (SameKey && uint((sc.timestamp - FirstTime) / 1000000) < uint(Setup.RcRepeatDelay))
|
||||
continue; // skip keys coming in too fast
|
||||
|
||||
if (!SameKey || (SeenRepeat && !(sc.flags & LIRC_SCANCODE_FLAG_REPEAT))) {
|
||||
// This is a key-press event, not key-repeat.
|
||||
if (repeat)
|
||||
Put(LastKeyCode, false, true); // generated release for previous key
|
||||
repeat = false;
|
||||
FirstTime = sc.timestamp;
|
||||
LastKeyCode = sc.keycode;
|
||||
LastFlags = sc.flags;
|
||||
}
|
||||
else if (uint((sc.timestamp - LastTime) / 1000000) < uint(Setup.RcRepeatDelta))
|
||||
continue; // filter out too frequent key-repeat events
|
||||
else
|
||||
repeat = true;
|
||||
|
||||
LastTime = sc.timestamp;
|
||||
Put(sc.keycode, repeat);
|
||||
}
|
||||
else {
|
||||
if (repeat) // the last one was a repeat, so let's generate a release
|
||||
Put(LastKeyCode, false, true);
|
||||
repeat = false;
|
||||
LastKeyCode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
14
lirc.h
14
lirc.h
@ -4,27 +4,23 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: lirc.h 1.4 2006/01/27 16:00:19 kls Exp $
|
||||
* $Id: lirc.h 5.1 2022/11/26 13:37:06 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __LIRC_H
|
||||
#define __LIRC_H
|
||||
|
||||
#include <sys/un.h>
|
||||
#include "remote.h"
|
||||
#include "thread.h"
|
||||
|
||||
class cLircRemote : public cRemote, private cThread {
|
||||
private:
|
||||
enum { LIRC_KEY_BUF = 30, LIRC_BUFFER_SIZE = 128 };
|
||||
class cLircRemote : public cRemote, protected cThread {
|
||||
protected:
|
||||
int f;
|
||||
struct sockaddr_un addr;
|
||||
virtual void Action(void);
|
||||
bool Connect(void);
|
||||
cLircRemote(const char *Name);
|
||||
public:
|
||||
cLircRemote(const char *DeviceName);
|
||||
virtual ~cLircRemote();
|
||||
virtual bool Ready(void);
|
||||
static void NewLircRemote(const char *Name);
|
||||
};
|
||||
|
||||
#endif //__LIRC_H
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user