Compare commits

...

301 Commits

Author SHA1 Message Date
Klaus Schmidinger
dd71a004e2 Official release of version 2.7.4 2025-02-26 10:35:03 +01:00
Klaus Schmidinger
45091fbd72 Revised locking in cMenuSchedule and cMenuWhatsOn 2025-02-25 15:53:43 +01:00
Klaus Schmidinger
988d5aebfa Added missing locks to SetMenuItem() functions 2025-02-20 10:23:15 +01:00
Klaus Schmidinger
8c3671fae6 Fixed cPtsIndex::FindFrameNumber() to handle the case where Pts points to an I-frame 2025-02-19 15:39:16 +01:00
Klaus Schmidinger
2a12af481a Fixed spurious fast frames when switching from "slow back" to "slow forward" 2025-02-18 17:06:15 +01:00
Klaus Schmidinger
7817e64695 Fixed progress display when switching from "pause" to "slow back" 2025-02-18 15:37:24 +01:00
Klaus Schmidinger
ebbaa39098 Added '~' to the list of delimiters in cTextWrapper 2025-02-17 11:13:13 +01:00
Klaus Schmidinger
d3dcbbd4f2 Fixed unnecessary redisplays of menus 2025-02-17 10:49:10 +01:00
Klaus Schmidinger
3045995bbc Fixed displaying the current item when pressing a hotkey 2025-02-13 13:58:07 +01:00
Klaus Schmidinger
1b4233d6ad The function cPlugin::MainThreadHook() has been deprecated 2025-02-12 22:22:20 +01:00
Klaus Schmidinger
34aa8fe8b4 Adjusted PLUGINS.html to the new API version numbering introduced in version 2.7.2 2025-02-12 22:02:25 +01:00
Klaus Schmidinger
baa97e9ff1 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 2025-02-12 21:18:53 +01:00
Klaus Schmidinger
03afc4a353 Fixed unnecessary calls to cStatus::OsdCurrentItem2() when scrolling 2025-02-05 22:12:32 +01:00
Klaus Schmidinger
ef4ebeb7ee The new virtual function cStatus::OsdCurrentItem2() can be used to get the index of the current menu item 2025-01-29 11:15:26 +01:00
Klaus Schmidinger
80d8851e62 Added cStatus::OsdCurrentItem2() 2025-01-29 11:15:26 +01:00
Klaus Schmidinger
ead135f716 Fixed unnecessary calls to DisplayCurrent() for editable menu items 2025-01-29 10:35:25 +01:00
Klaus Schmidinger
49dc61a92c Fixed an unnecessary redisplay of the menu when pressing a hotkey 2025-01-29 10:25:55 +01:00
Klaus Schmidinger
af0309cc40 Fixed an improper call of cStatus::OsdCurrentItem() before cStatus::OsdItem2() 2025-01-29 10:20:17 +01:00
Klaus Schmidinger
4ed7421b1c Activated logging of OsdItem2() 2025-01-28 10:41:03 +01:00
Klaus Schmidinger
3058354dba Fixed setting the file name of the info file after renaming a recording 2025-01-18 20:57:06 +01:00
Klaus Schmidinger
20a8c5d240 Added cStatus::OsdItem2() 2025-01-16 10:23:12 +01:00
Klaus Schmidinger
0749a34342 The new virtual function cStatus::OsdItem2() can be used to get the information whether a menu item is selectable 2025-01-16 09:42:11 +01:00
Klaus Schmidinger
e595eed57d The info files of recordings are now only re-read if they have been modified 2025-01-15 10:50:29 +01:00
Klaus Schmidinger
a7576f0b6c Added parameter checks to strn0cpy() and Utf8Strn0Cpy() 2025-01-15 08:57:45 +01:00
Klaus Schmidinger
657e5dda5d Added a header to the backtrace 2025-01-15 08:43:12 +01:00
Klaus Schmidinger
8fb6a2b24b Fixed handling margins for timers that are not VPS controlled and not spawned 2025-01-13 14:44:18 +01:00
Klaus Schmidinger
53cac302d8 Added 1 to Utf8BufSize() for worst case 2025-01-13 13:18:42 +01:00
Klaus Schmidinger
2c6c014dd8 Checking for VPS control is now limited to local timers 2025-01-13 12:34:18 +01:00
Klaus Schmidinger
a7071f580e Added some missing locking 2025-01-10 16:11:02 +01:00
Klaus Schmidinger
de5327a048 Fixed a possible deadlock when canceling an editing process 2025-01-10 13:12:04 +01:00
Klaus Schmidinger
7ab94c7bcb Fixed accessing a timer's event schedule in case the event has been removed from the schedule 2025-01-07 10:46:22 +01:00
Klaus Schmidinger
0f80fc5e86 Fixed handling the fps value if it can't be determined from the video data 2024-12-05 10:37:15 +01:00
Klaus Schmidinger
d169f30e5c TS packets with errors are now skipped when parsing for frames 2024-12-05 10:33:31 +01:00
Klaus Schmidinger
7a1842cba6 Fixed a typo 2024-12-04 14:33:22 +01:00
Klaus Schmidinger
e4e9d7a55f Added some missing locking 2024-12-02 12:40:56 +01:00
Klaus Schmidinger
ccbef6ce6c Fixed some typos in the translation files 2024-11-30 14:30:46 +01:00
Klaus Schmidinger
7461a1ba3a Updated the Finnish OSD texts 2024-10-24 09:58:43 +02:00
Klaus Schmidinger
bb55e3036e The VDR homepage is now accessible via HTTPS 2024-10-21 19:04:53 +02:00
Klaus Schmidinger
bbf2cca198 Updated the Italian OSD texts 2024-10-20 10:05:19 +02:00
Klaus Schmidinger
8ce034d124 Fixed wrong credits 2024-10-17 20:17:57 +02:00
Klaus Schmidinger
4030698007 Fixed error checking in case the fps value can't be determined by the frame parser 2024-10-13 13:34:32 +02:00
Klaus Schmidinger
66fea5c9f1 Removed all DEPRECATED_* code 2024-10-13 09:47:18 +02:00
Klaus Schmidinger
285574eeaa Official release of version 2.7.3 2024-10-12 13:32:46 +02:00
Klaus Schmidinger
55cfb057e0 Added vdrrootdir and incdir to vdr.pc 2024-10-11 14:21:04 +02:00
Klaus Schmidinger
b4c538cff7 The Channel+/- keys can now be used to jump between errors while replaying a recording 2024-10-11 14:10:50 +02:00
Klaus Schmidinger
5a626fef9f Fixed expiring of one-time VPS timers in case there is more than one event with the same VPS time 2024-10-11 13:58:11 +02:00
Klaus Schmidinger
2bcd8ba8f3 Fixed handling negative values in cSource::Position() on systems where 'int' is 64 bit 2024-10-09 10:36:16 +02:00
Klaus Schmidinger
2dacc776bd Fixed error checking in case of large PTS discontinuities 2024-10-08 08:46:38 +02:00
Klaus Schmidinger
a91d687a1a Removed defining DEPRECATED_* macros with value 0, because this is the preprocessor's default 2024-10-08 08:09:48 +02:00
Klaus Schmidinger
0d3882d43e Official release of version 2.7.2 2024-09-27 09:15:33 +02:00
Klaus Schmidinger
72ad601328 Added a note about re-generating the index of old recordings with errors 2024-09-27 09:14:23 +02:00
Klaus Schmidinger
2c6fd804f6 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 2024-09-26 19:25:41 +02:00
Klaus Schmidinger
c590444b7d Fixed error checking when regenerating the index 2024-09-21 19:18:18 +02:00
Klaus Schmidinger
4805af7915 Increased the bpp of cProgressBar to 4 to handle all different colors 2024-09-21 16:21:08 +02:00
Klaus Schmidinger
171b20a80d Fixed singular when displaying number of errors in the recording info 2024-09-21 10:53:07 +02:00
Klaus Schmidinger
d00ae923ab Edited recordings now show error count of original if there are no error indicators in the index 2024-09-20 21:34:18 +02:00
Klaus Schmidinger
d8ab5dc5c6 Fixed syncing the frame checker to I-frames 2024-09-20 14:21:39 +02:00
Klaus Schmidinger
292af5d4f4 The info file of an edited recording now contains the number of errors in the edited version 2024-09-19 20:21:58 +02:00
Klaus Schmidinger
3d6b31b115 When the index file of a recording is regenerated, errors in the recording are now stored in the index file 2024-09-19 12:06:55 +02:00
Klaus Schmidinger
9e523073aa Errors are now shown as diamond shaped markers in the replay progress display of the default skins 2024-09-19 09:49:02 +02:00
Klaus Schmidinger
32d8e473fb Fixed description of cSkinDisplayReplay::SetRecording() 2024-09-18 11:10:56 +02:00
Klaus Schmidinger
5cd25df60c Recording errors are now marked in the index file 2024-09-18 09:23:07 +02:00
Klaus Schmidinger
52c4816c9c Now distinguishing between frames with errors and completely missing frames 2024-09-17 11:30:28 +02:00
Klaus Schmidinger
6f6b05ffcb The number of errors in a recording now represents the number of broken frames 2024-09-17 09:39:50 +02:00
Klaus Schmidinger
6dd5854b7a Moved error checking from recorder.c to remux.c 2024-09-17 09:31:15 +02:00
Klaus Schmidinger
83425df0b6 Updated the Italian OSD texts 2024-09-16 09:14:41 +02:00
Klaus Schmidinger
82b09eaa8e Silenced a compiler warning with gcc 14.1.0 2024-09-16 09:07:12 +02:00
Klaus Schmidinger
ec5b1aadab Fixed a problem in cSchedule::Sort(), in case hasRunning was true, but there was no event with RunningStatus() >= SI::RunningStatusPausing 2024-09-14 14:17:12 +02:00
Klaus Schmidinger
f786510ba2 Made APIVERSION independent from VDRVERSION to avoid irritation in case only VDRVERSION is incremented 2024-09-12 12:48:40 +02:00
Klaus Schmidinger
f006884e57 Deprecated code is now marked with [[deprecated]] to issue a compile time warning when used 2024-09-09 22:15:59 +02:00
Klaus Schmidinger
c0a005b3cd Fix for compilers that don't like non-constant format strings 2024-09-09 13:39:05 +02:00
Klaus Schmidinger
0c91893643 There will be no more distinction between "developer" and "stable" versions regarding version numbering 2024-09-09 10:58:55 +02:00
Klaus Schmidinger
796da9e0f6 Improved the error message when closing a frontend 2024-09-09 08:53:57 +02:00
Klaus Schmidinger
5d539be071 The '.update' file in the video directory is now created if it doesn't already exist 2024-09-01 20:43:40 +02:00
Klaus Schmidinger
1df138d876 Fixed a crash when deleting a recording that is currently being edited, and then immediately deleting the edited version, too 2024-08-30 20:43:26 +02:00
Klaus Schmidinger
71b0140003 The new SVDRP command 'AUDI' can be used to list the currently available audio tracks and select one of them 2024-08-30 09:55:15 +02:00
Klaus Schmidinger
a33adf365d Changed the error message when trying to attach a player to a primary device without an MPEG decoder 2024-07-16 12:33:31 +02:00
Klaus Schmidinger
8d82b05071 Disabled/removed deprecated code 2024-07-15 14:42:22 +02:00
Klaus Schmidinger
930e3b4200 Official release of version 2.6.9 2024-07-15 09:07:09 +02:00
Klaus Schmidinger
2543f2c486 Added the lines from 'Fixed a timeout in cDvbDevice while tuning after the frontend has been reopened' to cDvbTuner::ProvidesFrontend() 2024-07-14 15:41:01 +02:00
Klaus Schmidinger
d919817c35 Fixed restarting the EPG scan and keeping the frequency of calls to Device->SetPowerSaveIfUnused() low 2024-07-13 20:12:24 +02:00
Klaus Schmidinger
6bbb596968 Fixed setting the editable width in the LCARS skin 2024-07-13 15:25:22 +02:00
Klaus Schmidinger
8aec1974bb Fixed a timeout in cDvbDevice while tuning after the frontend has been reopened 2024-07-13 12:34:42 +02:00
Klaus Schmidinger
b3ad9ec699 Fixed handling of cSkinDisplayMenu::GetTextAreaFont() 2024-07-13 09:12:18 +02:00
Klaus Schmidinger
87410442b6 Fixed a crash in strreplace() for multiple replacements with strings of different lengths 2024-07-10 14:59:45 +02:00
Klaus Schmidinger
305735a886 Official release of version 2.6.8 2024-07-08 18:40:20 +02:00
Klaus Schmidinger
41b7e1546a Added 'lnbPowerTurnedOn = false' to cDvbTuner::ProvidesFrontend() 2024-07-08 18:39:18 +02:00
Klaus Schmidinger
f3972e4795 Implemented power save mode for cDvbDevice 2024-07-08 09:34:33 +02:00
Klaus Schmidinger
e7ea087a6e Unused devices can now be put into a power save mode 2024-07-06 11:19:21 +02:00
Klaus Schmidinger
749ba57dcc Updated the Italian OSD texts 2024-07-02 07:57:42 +02:00
Klaus Schmidinger
0360b0d0e7 The EIT scanner now checks whether there is a proper device before adding a channel to the scan list 2024-06-27 10:49:34 +02:00
Klaus Schmidinger
2b495e0f87 Removed leftover cMenuRecordings::SetPath() 2024-06-25 19:00:06 +02:00
Klaus Schmidinger
32b11e1a53 Added an EPG bugfix for broadcasters who put literal "\n" strings in their EPG 2024-06-21 06:27:20 +02:00
Klaus Schmidinger
db81c07b27 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 2024-06-13 09:31:14 +02:00
Klaus Schmidinger
1c2401eb6c Fixed typos 2024-06-11 12:43:25 +02:00
Klaus Schmidinger
5828d347f7 Fixed setting T2 system ID from NIT 2024-05-29 11:13:34 +02:00
Klaus Schmidinger
9c64622718 Fixed a possible access of a deleted object in the EIT scanner 2024-05-19 14:55:57 +02:00
Klaus Schmidinger
f9260d0141 Updated the Italian OSD texts 2024-04-03 08:21:05 +02:00
Klaus Schmidinger
746cdaff01 Official release of version 2.6.7 2024-04-02 09:05:33 +02:00
Klaus Schmidinger
179d5b87fc A device is now always kept occupied if a timer is in VPS margin or needs the transponder 2024-03-29 21:46:50 +01:00
Klaus Schmidinger
51dca45a0c 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 2024-03-28 13:21:42 +01:00
Klaus Schmidinger
62ad9b41dd Added a missing initialization 2024-03-28 13:02:42 +01:00
Klaus Schmidinger
8b87a6968a The EIT scan is no longer inhibited if a timer is in VPS margin or needs the transponder 2024-03-10 11:26:54 +01:00
Klaus Schmidinger
faf562fd4e The EIT scan now skips scanList entries if a device is already tuned to that transponder 2024-03-10 11:16:29 +01:00
Klaus Schmidinger
6a09a2fbd6 The EIT scan no longer deletes the scanList if no device was switched in this pass 2024-03-10 10:38:18 +01:00
Klaus Schmidinger
bc32ffe2f9 Fixed logging when a timer has entered the VPS margin 2024-03-08 10:50:06 +01:00
Klaus Schmidinger
ff16bbd777 Logging event status changes now also shows the previous status 2024-03-06 20:16:51 +01:00
Klaus Schmidinger
f7f8a6b131 Improved handling present/following data for VPS timers 2024-03-06 14:37:15 +01:00
Klaus Schmidinger
a3310e2954 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 2024-03-04 21:14:27 +01:00
Klaus Schmidinger
0b08666310 Updated the Hungarian OSD texts 2024-03-04 15:04:26 +01:00
Klaus Schmidinger
42db3fbee0 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 2024-03-04 14:12:37 +01:00
Klaus Schmidinger
bfa25d6276 The primary device no longer starts unnecessary threads if it doesn't have a decoder 2024-03-04 12:26:32 +01:00
Klaus Schmidinger
824c495d33 Added a 15 second grace period before actually stopping a VPS timer 2024-03-03 15:47:09 +01:00
Klaus Schmidinger
561be36958 Adapted "Setup/Miscellaneous/Show channel names with source" to the new handling in cChannel 2024-03-02 21:49:21 +01:00
Klaus Schmidinger
8bd0437497 Modified handling channel names with source to make it thread safe 2024-03-02 16:21:16 +01:00
Klaus Schmidinger
18c9cef1ea Added missing initialization of cChannel::nameSourceMode 2024-03-01 14:33:28 +01:00
Klaus Schmidinger
2c66d57d4b Fixed the move assignment operator to check for self-assignment 2024-02-15 14:57:56 +01:00
Klaus Schmidinger
29200d040e Official release of version 2.6.6 2024-01-25 09:44:48 +01:00
Klaus Schmidinger
385738cadd Fixed possible duplicate component entries in the info of an ongoing recording 2024-01-24 13:24:51 +01:00
Klaus Schmidinger
a2591d6e98 Workaround in detecting frame height for channels with wrong crop parameters 2024-01-23 19:33:45 +01:00
Klaus Schmidinger
fe97a38e77 Fixed handling primary device on headless systems 2024-01-22 12:10:30 +01:00
Klaus Schmidinger
552f5fc4e7 Fixed a typo 2024-01-22 12:09:22 +01:00
Klaus Schmidinger
21d3d489fd Added '/' to the list of fuzzy characters for pattern timers 2024-01-21 10:43:20 +01:00
Klaus Schmidinger
78b7e4e252 Added the total number of errors when logging new recording errors 2024-01-20 20:04:03 +01:00
Klaus Schmidinger
5d984b606e Added the move constructor to cString for better performance 2024-01-20 13:59:55 +01:00
Klaus Schmidinger
88b1e30494 Fixed an unnecessary double display of menu items in the Recordings menu 2024-01-19 12:17:05 +01:00
Klaus Schmidinger
939071bf25 Fixed an unnecessary double display of the current menu item in page up/down 2024-01-19 12:10:47 +01:00
Klaus Schmidinger
655682b5d2 Removed syslog calls in child process after fork() 2024-01-18 13:01:07 +01:00
Klaus Schmidinger
b1418b6bcd Implemented scaling images 2024-01-18 12:04:57 +01:00
Klaus Schmidinger
35c8b3d22c Using a dummy OSD if no OSD provider is available is not considered an error any more 2024-01-18 11:06:45 +01:00
Klaus Schmidinger
e5ae02e3fa Fixed a possible crash in cDevice::StopSectionHandler() 2024-01-18 10:58:39 +01:00
Klaus Schmidinger
f0da21ea13 Fixed height calculation in progress display 2024-01-17 21:15:48 +01:00
Klaus Schmidinger
eb35faaf7d Changed installing config files to handle potentially broken 'cp -n' 2024-01-05 14:16:16 +01:00
Klaus Schmidinger
05f03d6e38 Official release of version 2.6.5 2023-12-30 10:27:34 +01:00
Klaus Schmidinger
0d4284df29 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) 2023-12-29 10:48:40 +01:00
Klaus Schmidinger
cade92cda1 Added the function cRecordingInfo::FrameParams(), which can be used to get a nicely formatted string with all the available frame data 2023-12-29 10:48:25 +01:00
Klaus Schmidinger
f0bbf64da0 Added cString::Append(char) 2023-12-29 10:24:29 +01:00
Klaus Schmidinger
6458f8b581 The frame width, height, scan type and apect ratio of a recording are now stored in the 'info' file under the 'F' tag 2023-12-28 21:23:19 +01:00
Klaus Schmidinger
1770a18598 Fixed broken video data streams on systems without output device when switching live channel to a different transponder while recording 2023-02-21 09:31:47 +01:00
Klaus Schmidinger
5f136032a2 Official release of version 2.6.4 2023-02-17 12:04:45 +01:00
Klaus Schmidinger
63efcf3927 Removed unnecessary empty lines 2023-02-16 17:20:09 +01:00
Klaus Schmidinger
468dc1115e Revised support for kernel based LIRC driver 2023-02-16 17:15:06 +01:00
Klaus Schmidinger
d53e0fd5c3 Fixed unnecessary interruption of ongoing recordings if timers avoided the transfer mode receiver device 2023-02-16 14:53:38 +01:00
Klaus Schmidinger
14b907b01c Fixed a possible crash if an editing process is canceled while the edited recording is being replayed (new solution) 2023-02-15 14:59:25 +01:00
Klaus Schmidinger
e0d87da768 Reverted 'Fixed a possible crash if an editing process is canceled while the edited recording is being replayed' 2023-02-15 14:01:20 +01:00
Klaus Schmidinger
42b584e38d Fixed initializing cDvbPlayerControl (was broken in version 2.6.3) 2022-12-27 15:57:20 +01:00
Klaus Schmidinger
a0f79bdd5f Added a note to vdr.5 about event ids possibly changing when an event moves from one table to another 2022-12-26 13:24:09 +01:00
Klaus Schmidinger
4372d55dd1 Added a note to epg.h about not messing with event ids 2022-12-24 11:37:17 +01:00
Klaus Schmidinger
13672280b6 Fixed symmetry of Begin/EndSegmentTransfer() calls in cEIT::cEIT() 2022-12-23 09:47:23 +01:00
Klaus Schmidinger
5b134cb23e Fixed restoring the volume at program start 2022-12-19 15:13:56 +01:00
Klaus Schmidinger
87cf0b7a3d Updated the Italian OSD texts 2022-12-16 12:17:03 +01:00
Klaus Schmidinger
8b14723e9e Official release of version 2.6.3 2022-12-14 09:38:41 +01:00
Klaus Schmidinger
7fe59548cd Now checking the video directory after setting the user id 2022-12-12 10:27:38 +01:00
Klaus Schmidinger
15f13ac936 Avoiding a zero sized array in cDevice::GetDevice() 2022-12-07 09:38:05 +01:00
Klaus Schmidinger
5b176f97a4 Now avoiding unnecessary processing in cDvbSubtitleConverter::FinishPage() if there are no areas 2022-12-06 16:57:01 +01:00
Klaus Schmidinger
0bb6f87776 Now avoiding the memcpy() call in cGlyph::cGlyph() if the bitmap is empty 2022-12-06 12:30:13 +01:00
Klaus Schmidinger
c06d2389e9 Now avoiding calling poll() in cSectionHandler::Action() if there are no filters 2022-12-06 12:25:08 +01:00
Klaus Schmidinger
548a33c728 Fixed initializing cPictureControl 2022-12-05 15:26:23 +01:00
Klaus Schmidinger
4336b55f4e Fixed initializing cDvbPlayerControl and cTransferControl 2022-12-05 14:45:51 +01:00
Klaus Schmidinger
c12c7378e9 Fixed a possible heap-use-after-free in cDvbTuner::Action() 2022-12-05 14:04:10 +01:00
Klaus Schmidinger
a299d8d348 Added code for the 'qks' audio track 2022-12-01 20:57:12 +01:00
Klaus Schmidinger
c7bf474a42 Fixed a faulty 'Timer still recording' query when canceling an editing job 2022-12-01 13:09:04 +01:00
Klaus Schmidinger
8d65cc6dc0 Fixed generating the index file in the cutter 2022-12-01 12:47:33 +01:00
Klaus Schmidinger
f2b9f0e8dd Fixed a compiler warning 2022-11-30 14:38:46 +01:00
Klaus Schmidinger
30f05ba714 Official release of version 2.6.2 2022-11-30 12:03:17 +01:00
Klaus Schmidinger
76445411a5 Added missing rounding when dividing frequencies in processing the NIT 2022-11-30 12:02:00 +01:00
Klaus Schmidinger
4425918d31 Fixed regenerating the index file of a recording in case it is present, but empty 2022-11-28 14:39:23 +01:00
Klaus Schmidinger
6888ea68b6 Added periodic calls to malloc_trim(0) to reduce memory consumption 2022-11-28 10:44:01 +01:00
Klaus Schmidinger
abb82a2396 Added support for kernel based LIRC driver 2022-11-26 13:37:06 +01:00
Klaus Schmidinger
6192ca81d9 Fixed name and email for Marko Mkel 2022-11-23 14:42:03 +01:00
Klaus Schmidinger
d06c5efa54 Avoiding a compiler warning 2022-11-22 15:53:07 +01:00
Klaus Schmidinger
f859b8d2ae Fixed printing/scanning values for systems where %ld doesn't work for time_t 2022-11-22 14:33:56 +01:00
Klaus Schmidinger
035d5fd5b9 Using the frame rate parsed from the stream, with fall back to determining it from PTS values 2022-11-22 11:35:37 +01:00
Klaus Schmidinger
93d578d9b8 Implemented parsing frame rate and image size for MPEG2, H.264 and H.265 2022-11-22 11:31:39 +01:00
Klaus Schmidinger
d756628297 Added a chapter about locking to PLUGINS.html 2022-11-20 21:38:18 +01:00
Klaus Schmidinger
a4cde807bc Added a missing 'const' to cTimers::GetTimerForEvent() 2022-11-20 10:57:31 +01:00
Klaus Schmidinger
83c9677899 Fixed a possible deadlock in case two SVDRP clients send each other POLL commands at the same time 2022-11-19 15:49:27 +01:00
Klaus Schmidinger
b14ed38a48 Removed some unnecessary locks from SVDRPClientHandler 2022-11-19 15:47:03 +01:00
Klaus Schmidinger
2bf0967a47 Fixed default values for DVB-T 2022-11-15 10:21:55 +01:00
Klaus Schmidinger
7ed306d127 Changed email address of Winfried Khler 2022-11-14 11:14:10 +01:00
Klaus Schmidinger
5a029eb29f Added a warning if an attempt is made to obtain a write lock twice from the same thread 2022-11-13 15:25:52 +01:00
Klaus Schmidinger
230adc8235 Fixed a possible crash if an editing process is canceled while the edited recording is being replayed 2022-11-13 15:23:13 +01:00
Klaus Schmidinger
982a9a5157 Setting the '.timer' file when regenerating the index file 2022-11-13 14:49:08 +01:00
Klaus Schmidinger
c8e4921a0a Now checking for '.timer' file to determine whether a recording is still active 2022-11-06 11:49:31 +01:00
Klaus Schmidinger
786245efe5 Now assuming the lock when removing deleted recordings even if the disk is full 2022-11-04 14:30:01 +01:00
Klaus Schmidinger
74460f22bf Now dropping capabilities after opening terminal 2022-06-01 14:24:57 +02:00
Klaus Schmidinger
a843d03af1 Fixed unexpected calls of the '-r' script when a recording is interrupted and the timer has not yet finished 2022-03-03 14:44:47 +01:00
Klaus Schmidinger
d3f3e856e4 Added UPDATE-2.6.0, which was missing in the official 2.6.0 release 2022-02-09 12:34:09 +01:00
Klaus Schmidinger
be3c6048ed Official release of version 2.6.1 2022-02-02 10:56:43 +01:00
Klaus Schmidinger
2a0222226a Clarified some potentially mistakable code in cSectionHandler::SetStatus() 2022-01-31 21:21:42 +01:00
Klaus Schmidinger
50c3951017 Fixed a possible deadlock in cDevice::DetachAllReceivers() 2022-01-24 16:53:45 +01:00
Klaus Schmidinger
ea1ad945b4 Fixed handling error conditions in the index file 2022-01-24 10:44:21 +01:00
Klaus Schmidinger
8cde8464eb Fixed handling zero bytes in cH264Parser 2022-01-18 14:24:33 +01:00
Klaus Schmidinger
14b108f104 Added some missing "AUTO" values to vdr.5 2022-01-14 10:46:15 +01:00
Klaus Schmidinger
330dbce1e7 Updated the Italian OSD texts 2022-01-14 10:27:26 +01:00
Klaus Schmidinger
adeb6314fb Fixed starting replay after jumping to an editing mark 2022-01-13 21:41:41 +01:00
Klaus Schmidinger
78a09b5926 Removed a TODO - detecting errors was implemented in version 2.5.4 2022-01-13 10:56:01 +01:00
Klaus Schmidinger
d05765c670 Replaced strncpy() with memcpy() in strreplace() to avoid a compiler warning 2021-12-30 14:38:40 +01:00
Klaus Schmidinger
a5a4b72d1c Fixed description of using number keys to toggle weekdays of a timer 2021-12-29 21:06:52 +01:00
Klaus Schmidinger
955b1c914f Official release of version 2.6.0 2021-12-27 13:31:29 +01:00
Klaus Schmidinger
5b28aa7e02 Added entries for backports to version 2.4.8 2021-12-27 13:27:16 +01:00
Klaus Schmidinger
f34a6d66a0 Removed a leftover debugging line 2021-12-25 14:11:39 +01:00
Klaus Schmidinger
104bddc560 Fixed calculating the disk use percentage if there's more than 20TB of recordings 2021-12-24 10:56:47 +01:00
Klaus Schmidinger
e7107b789e Fixed a possible memory leak in creating fonts 2021-12-20 13:19:52 +01:00
Klaus Schmidinger
f2e71eb668 Version 2.5.7 2021-12-20 10:06:37 +01:00
Klaus Schmidinger
f275346ecc Fixed a memory leak in handling the NIT 2021-12-14 21:15:02 +01:00
Klaus Schmidinger
33b47142e4 Fixed unlocking vs. call to EpgHandlers.EndSegmentTransfer() 2021-12-11 20:58:51 +01:00
Klaus Schmidinger
5f3d42bcd8 Added missing '0x09=H.265 video, 0x19 = AC4 audio' to vdr.5 2021-10-16 09:27:11 +02:00
Klaus Schmidinger
3f2dd916c1 Replaced all umlauts in the example channels.conf with their ae, oe, ue substitutes to avoid problems on UTF-8 systems 2021-07-26 12:39:42 +02:00
Klaus Schmidinger
0d50ec57f5 Version 2.5.6 2021-07-02 08:58:59 +02:00
Klaus Schmidinger
7301f2de08 The Recordings menu now marks recordings with errors, and the number of errors (if any) is displayed in the recording's Info menu 2021-07-01 15:40:46 +02:00
Klaus Schmidinger
8c7d387e86 Fixed triggering the PAT filter 2021-06-21 20:13:55 +02:00
Klaus Schmidinger
6c5a448dec Fixed deleting the edited recording in case of an error 2021-06-21 15:30:16 +02:00
Klaus Schmidinger
a84f9a8e19 Improved responsiveness in cSectionHandler::Action() 2021-06-20 10:27:19 +02:00
Klaus Schmidinger
545613e0e7 When checking whether a recording has already been made, recording names are now compared case insensitive 2021-06-20 10:03:28 +02:00
Klaus Schmidinger
ac4da6e380 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 2021-06-19 15:34:38 +02:00
Klaus Schmidinger
4d5cbaf57d If an error occurs while recording, the respective entry in the list of recordings is now updated immediately 2021-06-19 14:21:16 +02:00
Klaus Schmidinger
a4a2466bf4 Fixed restarting PMT pids after starting a recording on the currently viewed channel 2021-06-11 09:38:38 +02:00
Klaus Schmidinger
a0cdfc432a Version 2.5.5 2021-06-10 09:59:45 +02:00
Klaus Schmidinger
60c858689b Fixed handling incomplete multi-packet CAT 2021-06-09 09:42:15 +02:00
Klaus Schmidinger
9686a9b474 Removed unused declaration of cDvbTuner::SetFrontendType() 2021-06-09 09:12:25 +02:00
Klaus Schmidinger
0f6265a97f Fixed flushing old data from the section handler 2021-06-08 15:10:51 +02:00
Klaus Schmidinger
7b1c097958 No longer permanently looping through PMT PIDs, which caused problems with some SatIP receivers 2021-06-08 14:57:26 +02:00
Klaus Schmidinger
58e21d8e37 Now using __cplusplus instead of DISABLE_TEMPLATES_COLLIDING_WITH_STL, and using std::min(), std::max() and std::swap() if available 2021-05-26 13:37:53 +02:00
Klaus Schmidinger
e1f04cd6fa Added missing initialization of cRecorder::lastErrors 2021-05-25 20:14:06 +02:00
Klaus Schmidinger
7775698bac The error counter of a recording is now copied as is when editing a recording 2021-05-25 20:09:29 +02:00
Klaus Schmidinger
8f52603665 cRecordingInfo::Errors() now returns -1 for old recordings; added a missing 'const' 2021-05-23 15:03:17 +02:00
Klaus Schmidinger
c40fb4b4aa Version 2.5.4 2021-05-21 15:09:34 +02:00
Klaus Schmidinger
161fa8ead4 The default for DEPRECATED_SKIN_SETITEMEVENT has been set to 0 2021-05-21 13:03:42 +02:00
Klaus Schmidinger
115eb9fdb4 The macro DEPRECATED_GETBITMAP and the related code has been removed 2021-05-21 12:54:08 +02:00
Klaus Schmidinger
b7112ece6c The default for DEPRECATED_SETCURRENTCHANNEL has been set to 0 2021-05-21 12:51:16 +02:00
Klaus Schmidinger
f7c8f582ea The macro DEPRECATED_VDR_CHARSET_OVERRIDE and the related code has been removed 2021-05-21 12:43:18 +02:00
Klaus Schmidinger
ada85b693e The 'Edit path' dialog now also shows the total size of all recordings in that path 2021-05-21 10:41:46 +02:00
Klaus Schmidinger
a1a8c5d94c Added code for the 'qad' audio track 2021-05-21 09:50:57 +02:00
Klaus Schmidinger
505bcee926 The transponder value of channels is now cached 2021-05-21 09:38:34 +02:00
Klaus Schmidinger
c02c081d91 The cFile class has been partially deprecated 2021-05-20 10:13:43 +02:00
Klaus Schmidinger
c8566fab77 Removed 'register' from libsi/util.c to avoid a warning with ISO-C++17 2021-05-19 11:55:00 +02:00
Klaus Schmidinger
54c4e69299 Removed the macros __STL_CONFIG_H, _STL_ALGOBASE_H and _MOVE_H from tools.h 2021-05-19 11:50:24 +02:00
Klaus Schmidinger
31b87544f1 Recordings are now checked for errors 2021-05-19 11:22:20 +02:00
Klaus Schmidinger
cd3cda2654 Fixed cTsPayload::AtPayloadStart() to ignore TS packets from other PIDs 2021-05-11 20:47:31 +02:00
Klaus Schmidinger
c98fdd9120 Fixed a typo 2021-05-03 14:06:12 +02:00
Klaus Schmidinger
10ffd08c82 Fixed a possible crash in the Schedule menu, in case Setup.EPGLinger is 0 2021-04-29 09:19:58 +02:00
Klaus Schmidinger
4a199fe4ac Now using a separate fixed value for internal EPG linger time 2021-04-28 20:44:56 +02:00
Klaus Schmidinger
98fa6206ac Version 2.5.3 2021-04-20 14:25:33 +02:00
Klaus Schmidinger
ce23ba64bd Deleting expired timers is now triggered immediately after the timers are modified 2021-04-20 13:22:37 +02:00
Klaus Schmidinger
02c668a6a9 EXPIRELATENCY now only applies to VPS timers 2021-04-20 09:50:02 +02:00
Klaus Schmidinger
9de337d2ee 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 2021-04-18 14:56:40 +02:00
Klaus Schmidinger
fa8c7c35b5 Fixed the timer indicator in the Schedule menu in case an event is already over, but the timer is still recording 2021-04-17 09:44:01 +02:00
Klaus Schmidinger
3d13eb002f Now making sure that spawned timers with reduced start/stop margins actually record with the full margins 2021-04-16 16:26:47 +02:00
Klaus Schmidinger
b2fb654bb3 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 2021-04-13 13:54:00 +02:00
Klaus Schmidinger
cd834c79ba Fixed dropping outdated events 2021-04-13 13:35:17 +02:00
Klaus Schmidinger
65aafacd8e Now adjusting spawned timers before setting events to timers 2021-04-10 11:32:50 +02:00
Klaus Schmidinger
ebd92dcd31 Fixed logging the old timer data in cTimer::AdjustSpawnedTimer() 2021-04-10 11:32:50 +02:00
Klaus Schmidinger
0003d6391c When spawning pattern timers, the new function cTimers::GetTimerForEvent() is now used to check whether a matching event already has a local timer 2021-04-10 10:09:50 +02:00
Klaus Schmidinger
4e52547a59 cTimer::TriggerRespawn() now only acts on local timers 2021-04-06 14:25:05 +02:00
Klaus Schmidinger
d3755c92d7 Version 2.5.2 2021-04-06 10:04:24 +02:00
Klaus Schmidinger
d536cf0947 No longer switching devices for pattern timers 2021-04-06 10:00:27 +02:00
Klaus Schmidinger
19a0e3cda7 Fixed MakePatternFileName() in case the event doesn't yet have a short text 2021-04-06 09:50:30 +02:00
Klaus Schmidinger
7fb13b3cbf Fixed handling the timer counter in cSchedule::DelEvent() 2021-04-06 09:01:26 +02:00
Klaus Schmidinger
23d986657a Spawned timers that don't use VPS now automatically adjust their start/stop times to changes in the respective event's times 2021-04-06 08:48:35 +02:00
Klaus Schmidinger
8f1419fff5 The margins for timer recordings are now always limited to the duration of the previous and next event 2021-04-04 13:38:13 +02:00
Klaus Schmidinger
b80c22e9c4 Improved handling EPG data from the EIT tables 2021-04-04 11:06:30 +02:00
Klaus Schmidinger
f672fe90c1 Fixed scaling subtitles with anti-aliasing 2021-03-17 15:24:34 +01:00
Klaus Schmidinger
3d55d3045e Decreased the scrambling timeout for CAMs known to decrypt a certain channel 2021-03-17 10:59:36 +01:00
Klaus Schmidinger
7ffc1a5efe Made checking for done recordings more tolerant 2021-03-17 10:55:43 +01:00
Klaus Schmidinger
36a833053b Improved cSectionSyncer 2021-03-16 15:10:54 +01:00
Klaus Schmidinger
ad35c9c2d3 Added some missing user command calls for copying, renaming and moving recordings 2021-01-19 20:38:28 +01:00
Klaus Schmidinger
1b1465a677 Now making sure a spawned timer only fully overlaps the given event 2021-01-19 13:21:51 +01:00
Klaus Schmidinger
2f6ce68ca7 Fixed setting the 'title' of a recording's info to the recording's name if there is no info file 2021-01-18 13:35:16 +01:00
Klaus Schmidinger
dee1225fa4 Made the functions cRecordingInfo::SetData() and cRecordingInfo::SetAux() public 2021-01-18 12:55:47 +01:00
Klaus Schmidinger
d78d6fba7e Spawned timers are now preferred over pattern timers in the Schedule menu 2021-01-15 13:52:40 +01:00
Klaus Schmidinger
80bdc90650 Now explicitly triggering respawning of pattern timers 2021-01-14 10:29:05 +01:00
Klaus Schmidinger
c402d57809 Increased the number of possible modulation systems in cDevice::GetDevice() 2021-01-11 10:36:05 +01:00
Klaus Schmidinger
f1836af0b0 Fixed VPS handling when spawning a pattern timer, in case Setup.UseVps is false 2021-01-07 16:00:17 +01:00
Klaus Schmidinger
eebcc57079 Fixed initializing the cChannel::schedule pointer after reading EPG data with PUTE 2021-01-04 09:05:26 +01:00
Klaus Schmidinger
cbc04d73b8 Added entries for backports to version 2.4.7 2021-01-02 15:37:57 +01:00
Klaus Schmidinger
be9eff0fad Fixed handling $(PKG_CONFIG) in newplugin 2021-01-02 14:32:20 +01:00
Klaus Schmidinger
3f3e47d280 Fixed a crash in the SVDRP command CLRE in case a non-existing channel number is given 2021-01-01 21:23:00 +01:00
Klaus Schmidinger
40ca081ff4 Using strgetlast() in more places 2021-01-01 15:26:27 +01:00
Klaus Schmidinger
c46fd1ff5b The Makefile now makes sure the 'x' bit of Doxyfile.filter is set before calling doxygen 2020-12-31 11:15:11 +01:00
Klaus Schmidinger
55b237dbe8 Fixed strreplace() to handle NULL strings 2020-12-29 21:40:29 +01:00
Klaus Schmidinger
2b3556b460 Implemented "Pattern Timers" 2020-12-26 15:49:01 +01:00
Klaus Schmidinger
d2e0087c4e Official release of version 2.4.6 2020-12-22 17:23:51 +01:00
Klaus Schmidinger
9a650a4772 Fixed convertCharacterTable() in case iconv_open() fails 2020-12-19 14:41:41 +01:00
Klaus Schmidinger
f4739f89bf Whitespace cleanup 2020-12-18 23:02:47 +01:00
Klaus Schmidinger
7ade54dfd7 Fixed a compiler warning 2020-12-18 14:51:57 +01:00
Klaus Schmidinger
45fde332a0 Fixed initializing tmpbuf in ExtendedEventDescriptors::getText() 2020-12-17 12:52:57 +01:00
Klaus Schmidinger
82cc5c76a4 Improved handling missing VDRPluginDestroyer() 2020-12-16 11:54:06 +01:00
Klaus Schmidinger
67a4ba4228 Fixed error handling when loading a plugin 2020-12-13 10:56:36 +01:00
Klaus Schmidinger
79a3607d0c Avoiding a lengthy lock on the Channels list when starting a recording 2020-12-12 22:01:01 +01:00
Klaus Schmidinger
dffeabbacb Fixed PMT handling in case locking the Channels list times out 2020-12-12 10:31:52 +01:00
Klaus Schmidinger
9fa7de2036 Fixed a bug in handling shared PMTs, where after the first pass not all SIDs of a PMT pid were checked any more 2020-12-09 21:42:26 +01:00
Klaus Schmidinger
bacc873896 Added initialization of cDvbFrontend::frontendInfo 2020-12-05 15:48:40 +01:00
Klaus Schmidinger
375d25627d Fixed generating the HashId in cEIT::cEIT() 2020-11-28 21:45:05 +01:00
Klaus Schmidinger
56e2ed2628 Fixed "read incomplete section" errors 2020-11-24 21:19:49 +01:00
Klaus Schmidinger
ad55da4ef9 Fixed possible compilation errors with libjpeg 2020-11-22 13:32:05 +01:00
Klaus Schmidinger
272231467a Fixed parsing the '-l' command line option 2020-11-20 13:49:58 +01:00
Klaus Schmidinger
6cb818c7ad Fixed allocating memory for cImage 2020-11-16 15:53:53 +01:00
Klaus Schmidinger
c23547c4ca Fixed a crash in case an error occurs when setting a remote timer 2020-11-06 13:13:05 +01:00
Klaus Schmidinger
0468b38ff3 Fixed an unnecessary double call to Display() in cMenuRecording::RefreshRecording() 2020-11-03 22:12:38 +01:00
Klaus Schmidinger
ebbc562aab Fixed multiple recording entries in case a recording is started during the initial reading of the video directory 2020-11-01 10:29:07 +01:00
178 changed files with 6748 additions and 1557 deletions

View File

@ -1226,6 +1226,9 @@ Peter Bieringer <pb@bieringer.de>
for suggesting to ignore lines tagged with '#' in the 'info.vdr' file of a recording
for reporting a problem with the backslash ('\') in parameters when executing
external commands
for making the functions cRecordingInfo::SetData() and cRecordingInfo::SetAux() public
for adding some missing user command calls for copying, renaming and moving recordings
for fixing scaling subtitles with anti-aliasing
Alexander Damhuis <ad@phonedation.de>
for reporting problems when deleting a timer that is currently recording
@ -2184,8 +2187,9 @@ Hardy Flor <HFlor@web.de>
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
@ -2196,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
@ -2339,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
@ -2442,6 +2459,21 @@ Christoph Haubrich <christoph1.haubrich@arcor.de>
for reporting a problem with data loss in case renaming a recording fails
for adding support for HEVC-video and AC-4-audio
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
@ -2520,6 +2552,50 @@ Nino Gerbino <ngerb@interfree.it>
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
@ -2645,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
@ -2751,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()
@ -2766,6 +2843,23 @@ Winfried K
for reporting a bug in handling newline characters in ci.c's CopyString()
for reporting a bug in checking the return value of the Open() call in
cFileName::SetOffset()
for adding initialization of cDvbFrontend::frontendInfo
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
@ -2868,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
@ -2931,6 +3026,11 @@ Manuel Reimer <Manuel.Reimer@gmx.de>
for reporting a bug in moving channels between number groups in SVDRP's MOVC command
for fixing compatibility with current versions of glibc
for suggesting to make the SVDRP command DELC accept a channel id
for reporting a crash in the SVDRP command CLRE in case a non-existing channel
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
@ -2984,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
@ -3273,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
@ -3335,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
@ -3484,6 +3603,10 @@ Stefan Schallenberg <infos@nafets.de>
Claus Muus <email@clausmuus.de>
for adding the new parameters "Setup/Miscellaneous/Volume steps" and
".../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
@ -3524,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
@ -3585,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
@ -3628,6 +3758,20 @@ Helmut Binder <cco@aon.at>
possible error message
for initializing the status variable in cDvbTuner::GetFrontendStatus() and
cDvbTuner::GetSignalStats() to avoid problems with drivers that don't do this
for fixing "read incomplete section" errors
for fixing generating the HashId in cEIT::cEIT()
for fixing a bug in handling shared PMTs, where after the first pass not all SIDs of a
PMT pid were checked any more
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
@ -3640,9 +3784,37 @@ J
for reporting a possible discrepancy of the primary device number in the LSTD and
PRIM commands
for adding support for EAC3 audio from other sources
for reporting a crash if a pattern timer spawns a timer that uses EPISODE and the
event has no short text
for reporting a bug in VPS handling when spawning a pattern timer, in case Setup.UseVps
is false
for reporting an endless spawning of pattern timers in case the spawned timer doesn't
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
Jens Schleusener <Jens.Schleusener@fossies.org>
for reporting several typos
Bernd Kuhls <bernd.kuhls@t-online.de>
for fixing possible compilation errors with libjpeg
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"

554
HISTORY
View File

@ -9535,3 +9535,557 @@ Video Disk Recorder Revision History
- Now initializing the status variable in cDvbTuner::GetFrontendStatus() and
cDvbTuner::GetSignalStats() to avoid problems with drivers that don't do this
(thanks to Helmut Binder).
2020-12-22: Version 2.4.6
- Fixed multiple recording entries in case a recording is started during the initial
reading of the video directory (reported by Claus Muus).
- Fixed an unnecessary double call to Display() in cMenuRecording::RefreshRecording()
(reported by Christoph Haubrich).
- Fixed a crash in case an error occurs when setting a remote timer.
- Fixed allocating memory for cImage (reported by Christoph Haubrich).
- Fixed parsing the '-l' command line option (reported by Harald Milz).
- Fixed possible compilation errors with libjpeg (thanks to Bernd Kuhls).
- Fixed "read incomplete section" errors (thanks to Helmut Binder).
- Fixed generating the HashId in cEIT::cEIT() (thanks to Helmut Binder).
- Added initialization of cDvbFrontend::frontendInfo (thanks to Winfried Köhler).
- Fixed a bug in handling shared PMTs, where after the first pass not all SIDs of a
PMT pid were checked any more (thanks to Helmut Binder).
- Fixed PMT handling in case locking the Channels list times out (reported by Helmut
Binder).
- Avoiding a lengthy lock on the Channels list when starting a recording (thanks to
Helmut Binder).
- Fixed error handling when loading a plugin (reported by Markus Ehrnsperger).
- Improved handling missing VDRPluginDestroyer() (thanks to Winfried Köhler).
- Fixed initializing tmpbuf in ExtendedEventDescriptors::getText() (thanks to Helmut
Binder).
- Fixed a compiler warning (thanks to Winfried Köhler).
- Fixed convertCharacterTable() in case iconv_open() fails (thanks to Helmut Binder).
- Official release.
2020-12-26: Version 2.5.1
- Implemented "Pattern Timers" (see MANUAL, vdr.1 and vdr.5 for details).
- Events in the past are no longer marked as having a timer in the Schedules
menu.
2021-01-02: Version 2.4.7
- Fixed strreplace() to handle NULL strings (reported by Jürgen Schneider).
- Somewhere down the road the 'x' bit of Doxyfile.filter got lost, so the
Makefile now makes sure it is set before calling doxygen.
- Fixed a crash in the SVDRP command CLRE in case a non-existing channel number is
given (reported by Manuel Reimer).
- Fixed handling $(PKG_CONFIG) in newplugin (thanks to Winfried Köhler).
2021-04-06: Version 2.5.2
- Fixed strreplace() to handle NULL strings (reported by Jürgen Schneider).
- Somewhere down the road the 'x' bit of Doxyfile.filter got lost, so the
Makefile now makes sure it is set before calling doxygen.
- Using strgetlast() in more places.
- Fixed a crash in the SVDRP command CLRE in case a non-existing channel number is
given (reported by Manuel Reimer).
- Fixed handling $(PKG_CONFIG) in newplugin (thanks to Winfried Köhler).
- Fixed initializing the cChannel::schedule pointer after reading EPG data with PUTE
(reported by Manuel Reimer).
- Fixed VPS handling when spawning a pattern timer, in case Setup.UseVps is false
(reported by Jürgen Schneider).
- Increased the number of possible modulation systems in cDevice::GetDevice()
(reported by Ulf Grüne).
- Now explicitly triggering respawning of pattern timers.
- If an event in the Schedules menu is marked with a 'T' or 'I' and the user presses the
Red button to edit the timer, spawned timers are now preferred over pattern timers
in case there is more than one timer that will match that event.
- Made the functions cRecordingInfo::SetData() and cRecordingInfo::SetAux() public
(thanks to Peter Bieringer).
- 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').
- Now making sure a spawned timer only fully overlaps the given event (reported by
Jürgen Schneider).
- Added some missing user command calls for copying, renaming and moving recordings
(thanks to Peter Bieringer).
- 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.
- When checking whether a particular recording has already been made by a pattern
timer, the characters ' ' (blank), ':' and '-' are now ignored, making
"TITLE - EPISODE" and "TITLE: EPISODE" the same.
- Decreased the scrambling timeout for CAMs known to decrypt a certain channel, so
that it won't collide with MAXBROKENTIMEOUT in recorder.c.
- Fixed scaling subtitles with anti-aliasing (thanks to Peter Bieringer).
- 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.
- 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.
- Fixed handling the timer counter in cSchedule::DelEvent().
- Fixed MakePatternFileName() in case the event doesn't yet have a short text (reported
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.

38
INSTALL
View File

@ -1,7 +1,7 @@
Installation of the Video Disk Recorder
---------------------------------------
Version 2.4
Version 2.7
-----------
Compiling and running the program:
@ -264,11 +264,10 @@ Executing commands before and after a recording:
------------------------------------------------
You can use the '-r' option to define a program or script that gets called
before and after a recording is performed, and after an editing process
has finished or a recording has been deleted.
at various stages of handling recordings.
The program will be called with two or three (in case of "editing" and "edited")
string parameters. The first parameter is one of
The program will be called with two or three string parameters.
The first parameter is one of
before if this is *before* a recording starts
started if this is after a recording has *started*
@ -276,13 +275,16 @@ string parameters. The first parameter is one of
editing if this is before *editing* a recording
edited if this is after a recording has been *edited*
deleted if this is after a recording has been *deleted*
copying if this is before *copying* a recording
copied if this is after a recording has been *copied*
renamed if this is after a recording has been *renamed*
moved if this is after a recording has been *moved*
(note that a move across file system borders triggers a sequence
of "copying", "copied" and "deleted")
and the second parameter contains the full name of the recording's
and the second and third parameter (if present) contain the full name of the recording's
directory (which may not yet exists at that moment in the "before" case).
In the "editing" and "edited" case it will be the name of the edited version
(second parameter) and the name of the source version (third parameter).
In the "deleted" case the extension of the directory name is ".del"
instead of ".rec".
See the example below for the exact meaning of these parameters.
Within this program you can do anything you would like to do before and/or
after a recording or after an editing process. However, the program must return
@ -315,6 +317,22 @@ case "$1" in
deleted)
echo "Deleted recording $2"
;;
copying)
echo "Destination recording $2"
echo "Source recording $3"
;;
copied)
echo "Destination recording $2"
echo "Source recording $3"
;;
renamed)
echo "New name of recording $2"
echo "Old name of recording $3"
;;
moved)
echo "New path of recording $2"
echo "Old path of recording $3"
;;
*)
echo "ERROR: unknown state: $1"
;;

157
MANUAL
View File

@ -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).
@ -480,6 +480,8 @@ Version 2.4
"forever", and a value of 0 means that this recording can be
deleted any time if a recording with a higher priority needs disk
space.
Pattern: The pattern to use for recordings matching events (only available
for pattern timers). See section "Pattern timers" below.
File: The name under which a recording created through this timer will
be stored on disk (the actual name will also contain the date and
time, so it is possible to have a "repeating timer" store all its
@ -511,6 +513,140 @@ Version 2.4
The "Red" key in the "Edit timer" menu opens a list of folders, which can be
used to define the file name in which the recording will be stored.
The "Yellow" key in the "Edit timer" menu toggles the timer between "Pattern"
and "Regular".
When editing the "File" field, the "Blue" key in can be used to insert useful
macros.
* Pattern timers
There are cases where it would make sense to have a more flexible kind of
recording timer. For instance, some channels that provide VPS don't always
use the exact same VPS time for a series, which is extremely annoying.
Or you might want to record all films that have a certain pattern in their
title, no matter when they are broadcast. In such cases, "pattern timers"
can help.
In the "Edit timer" menu press the Yellow button to turn a regular timer into
a pattern timer. Pressing this button again switches back to regular.
The following rules apply to pattern timers:
- Pattern timers can only work for channels that provide EPG data.
- When using pattern timers, there should always be at least one free device that
can be used to regularly receive the EPG of the pattern timer's channel.
- A pattern timer records every matching event on the given channel that overlaps
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. 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
a start/stop time of 00:00/23:59 will record every event of that day
into separate recordings. Note that when using this pattern there should
be no other timers for the same channel, because these might interfere.
- Once a timer has been spawned, it is treated like any other regular
timer. Any changes made to the corresponding pattern timer thereafter will have
no effect on spawned timers. Note that after deleting a spawned timer,
the corresponding pattern timer may respawn it.
- 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.
- The recording of a pattern timer is stored under the given file name, just like
regular timers do. In addition to the "TITLE" and "EPISODE" macros the file
name of a pattern timer can also use "{<}" and "{>}" to reference the part of the
event's title before and after the pattern, respectively. For instance,
if the event's title is "Abc def ghi" and the pattern is "def ", "{<}"
would contain "Abc " and "{>}" would contain "ghi" (note the matching of the
blanks). For completeness, "{=}" can be used to reference the matching
pattern itself.
- In the "Timers" menu pressing the Red button on a pattern timer only toggles the
timer between "on" and "off", even if this is a repeating timer.
- In the "Timers" menu pattern timers are sorted alphabetically to the end of the
list of timers.
- A regular timer that is currently recording can't be changed into a pattern timer.
- In the "Edit timer" menu the file name and pattern are displayed as
separate items. The Yellow button can be used to toggle between a regular
timer and a pattern timer. When going from regular to pattern, the Pattern item will
be initialized with the base part of the file name.
- The characters '^' and '$' can be used at the very beginning and end of
the pattern to anchor the pattern to the begin or end of the title.
Using both of these will match only titles that consist of exactly the given pattern,
with nothing before and nothing after it.
- The Pattern field in the "Edit timer" menu allows blanks at the end of the string,
which may help to separate the text after the matching pattern.
- If the first character of the pattern is '@', an event that matches the
rest of the pattern is only recorded if the resulting recording's file
name (without any folders) is not contained in the donerecs.data file.
This avoids duplicate recordings of the same programme. Timers spawned from
such a pattern timer are marked with the flag tfAvoid.
- When editing the "File" field of a timer, the Blue button can be pressed to
insert one of the macros "TITLE", "EPISODE", "{<}", "{=}" or "{>}",
respectively. Pressing the Blue button repeatedly loops through the available
macros. The "{...}" macros are only available for pattern timers.
- In the "Schedule" and "What's on...?" menus the events that will be recorded
by a pattern timer are marked in the same way as regular timers.
- The TIMERS column in the LCARS skin doesn't show the basic definitions of
pattern timers, it only shows timers actually spawned from pattern timers.
If the pattern is prepended with '@', the name of the resulting recording (everything
after the rightmost '~', or the entire file name, if there is no '~') will be stored
in the file donerecs.data, so that multiple recordings of the same programme can be
avoided. When using this feature, special care must be taken regarding the recording's
file name. For instance, with a combination of
pattern file name
@Columbo Movies~TITLE
if the event's title is just "Columbo", this pattern timer would only record once,
and ignore any future events with that title, even if the episode would be different.
So you may want to use the episode name, as in
pattern file name
@Columbo Movies~TITLE - EPISODE
to make the file name unique. If you have several pattern timers for the same show on
different channels, chances are that the broadcasters handle title and episode
differently, as for example in
TITLE EPISODE pattern file name
Columbo Blueprint for Murder @^Columbo$ TITLE - EPISODE
Columbo - Blueprint for Murder @^Columbo TITLE
Columbo: Blueprint for Murder @^Columbo:_ Columbo - {>}
(note the '_' in the pattern of the third example; this is just used to visualize
the blank at the end of the pattern)
In order to have the same episode result in the same recording file name on all
channels, the file name needs to be generated differently for each channel. First
you need to decide on a proper combination of title and episode name, preferably
one that is already used by one of your channels (let's say the second one).
In the first case, title and episode name are correctly put in their respective
places, and "TITLE - EPISODE" as file name will do. The second case is our common
version, where everything is in the title, so TITLE is just fine. The third case
poses a problem, because everything is in the title, but with a different separator.
Here the special macro "{>}" can be used in the file name, which contains everything
following the matching pattern. There are three macros that can be used here:
{<} everything before the matching pattern
{>} everything after the matching pattern
{=} the matching pattern itself (just for completeness)
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
The "Select folder" menu, which can be accessed by pressing the "Red" key in
@ -693,6 +829,16 @@ Version 2.4
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
@ -894,6 +1040,9 @@ Version 2.4
after the official end time it shall stop recording.
These margins are added automatically to timers that
are created from the EPG data.
Note that the actual margins used may be smaller than the
given values, if the event before and/or after the event
to be recorded is shorter than the respective margin.
Default priority = 50 The default Priority and Lifetime values used when
Default lifetime = 99 creating a new timer event. A Lifetime value of 99

View File

@ -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

View File

@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
# $Id: Makefile 4.10 2020/06/27 09:13:04 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\
@ -342,6 +351,7 @@ install-pc: vdr.pc
srcdoc:
@cat $(DOXYFILE) > $(DOXYFILE).tmp
@echo PROJECT_NUMBER = $(VDRVERSION) >> $(DOXYFILE).tmp
@chmod +x $(DOXYFILE).filter
$(DOXYGEN) $(DOXYFILE).tmp
@rm $(DOXYFILE).tmp
@ -350,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

View File

@ -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 &copy; 2018 Klaus Schmidinger<br>
Copyright &copy; 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-&gt;First(); Timer; Timer = Timers-&gt;Next(Timer)) {
// do something with Timer
}
}
</pre></td></tr></table><p>
Note the naming convention: TIMERS -&gt; 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>

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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");

View File

@ -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;

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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ą"

View File

@ -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"

View File

@ -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 "²ëÚÛ. ÓàÞÜÚÞáâì"

View File

@ -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"

View File

@ -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();

View File

@ -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().

View File

@ -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

View File

@ -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)

View File

@ -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.

View File

@ -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
View File

@ -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.

View File

@ -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
View 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.

View File

@ -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;

View File

@ -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

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: channels.h 4.5 2020/06/10 14:00:36 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);
@ -178,6 +180,7 @@ public:
void SetNumber(int Number) { number = Number; }
bool GroupSep(void) const { return groupSep; }
const char *Parameters(void) const { return parameters; }
const cSchedule *Schedule(void) const { return schedule; }
const cLinkChannels* LinkChannels(void) const { return linkChannels; }
const cChannel *RefChannel(void) const { return refChannel; }
bool IsAtsc(void) const { return cSource::IsAtsc(source); }

6
ci.c
View File

@ -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

View File

@ -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);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.h 4.20 2020/09/29 14:09:26 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.4.5"
#define VDRVERSNUM 20405 // 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.4.5"
#define APIVERSNUM 20405 // 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)
@ -46,6 +48,13 @@
#define TIMERMACRO_TITLE "TITLE"
#define TIMERMACRO_EPISODE "EPISODE"
#define TIMERMACRO_BEFORE "{<}"
#define TIMERMACRO_MATCH "{=}"
#define TIMERMACRO_AFTER "{>}"
#define TIMERPATTERN_AVOID "@"
#define TIMERPATTERN_BEGIN "^"
#define TIMERPATTERN_END "$"
#define MINOSDWIDTH 480
#define MAXOSDWIDTH 1920
@ -284,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;

View File

@ -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");

View File

@ -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:

135
device.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: device.c 4.36 2020/09/16 13:48:33 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 <<= 4; imp |= GetClippedNumProvidedSystems(4, device[i]) - 1; // avoid cards which support multiple delivery systems
imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice(); // avoid the Transfer Mode receiver device
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 <<= 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])
@ -1802,11 +1851,13 @@ bool cDevice::AttachReceiver(cReceiver *Receiver)
Receiver->scramblingTimeout = TS_SCRAMBLING_TIMEOUT;
bool KnownToDecrypt = ChannelCamRelations.CamDecrypt(Receiver->ChannelID(), camSlot->MasterSlotNumber());
if (KnownToDecrypt)
Receiver->scramblingTimeout *= 10; // give it time to receive ECM/EMM
Receiver->scramblingTimeout *= 9; // give it time to receive ECM/EMM (must be less than MAXBROKENTIMEOUT in recorder.c!)
if (Receiver->ChannelID().Valid())
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 -------------------------------------------------------------

View File

@ -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);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbdevice.c 4.27 2020/10/16 13:58:45 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;
@ -367,6 +370,8 @@ cDvbFrontend::cDvbFrontend(int Adapter, int Frontend)
frontend = Frontend;
fd_frontend = -1;
subsystemId = cDvbDeviceProbe::GetSubsystemId(adapter, frontend);
memset(&frontendInfo, 0, sizeof(frontendInfo));
strn0cpy(frontendInfo.name, "???", sizeof(frontendInfo.name));
numModulations = 0;
Open();
QueryDeliverySystems();
@ -389,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;
}
}
@ -544,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; }
@ -589,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;
@ -692,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;
}
@ -855,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) {
@ -872,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];
@ -1222,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' ;-)
@ -1287,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];
@ -1532,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));
}
@ -1764,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 {
@ -1854,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...
@ -2138,11 +2182,17 @@ bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
return true;
}
#define RB_NUM_SECTIONS 8 // default: 2 sections = 8192 bytes
int cDvbDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
{
cString FileName = DvbName(DEV_DVB_DEMUX, adapter, frontend);
int f = open(FileName, O_RDWR | O_NONBLOCK);
if (f >= 0) {
if (Pid == EITPID) { // increase ringbuffer size for EIT
if (ioctl(f, DMX_SET_BUFFER_SIZE, MAX_SECTION_SIZE * RB_NUM_SECTIONS) < 0)
dsyslog("OpenFilter (pid=%d, tid=%02X): ioctl DMX_SET_BUFFER_SIZE failed", Pid, Tid);
}
dmx_sct_filter_params sctFilterParams;
memset(&sctFilterParams, 0, sizeof(sctFilterParams));
sctFilterParams.pid = Pid;
@ -2290,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)) {

View File

@ -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:

View File

@ -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) {

View File

@ -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.

View File

@ -8,7 +8,7 @@
*
* parts of this file are derived from the OMS program.
*
* $Id: dvbspu.c 2.11 2013/02/22 15:25:16 kls Exp $
* $Id: dvbspu.c 4.1 2020/12/18 14:51:57 kls Exp $
*/
#include "dvbspu.h"
@ -38,7 +38,7 @@
#ifdef SPUDEBUG
#define DEBUG(format, args...) printf (format, ## args)
#else
#define DEBUG(format, args...)
#define DEBUG(format, args...) void()
#endif
// --- cDvbSpuPalette---------------------------------------------------------

View File

@ -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 4.2 2020/05/15 12:32:51 kls Exp $
* $Id: dvbsubtitle.c 5.2 2022/12/06 16:57:01 kls Exp $
*/
#include "dvbsubtitle.h"
@ -993,7 +993,9 @@ public:
int64_t Pts(void) const { return pts; }
bool Pending(void) { return pending; }
cSubtitleObjects *Objects(void) { return &objects; }
tArea *GetAreas(int &NumAreas, double FactorX, double FactorY);
tArea *GetAreas(int &NumAreas);
tArea CombineAreas(int NumAreas, const tArea *Areas);
tArea ScaleArea(const tArea &Area, double FactorX, double FactorY);
cSubtitleObject *GetObjectById(int ObjectId, bool New = false);
cSubtitleClut *GetClutById(int ClutId, bool New = false);
cSubtitleRegion *GetRegionById(int RegionId, bool New = false);
@ -1077,7 +1079,7 @@ void cDvbSubtitlePage::ParsePgs(int64_t Pts, cBitStream &bs)
pending = true;
}
tArea *cDvbSubtitlePage::GetAreas(int &NumAreas, double FactorX, double FactorY)
tArea *cDvbSubtitlePage::GetAreas(int &NumAreas)
{
if (regions.Count() > 0) {
NumAreas = regionRefs.Count();
@ -1085,13 +1087,11 @@ tArea *cDvbSubtitlePage::GetAreas(int &NumAreas, double FactorX, double FactorY)
tArea *a = Areas;
for (cSubtitleRegionRef *srr = regionRefs.First(); srr; srr = regionRefs.Next(srr)) {
if (cSubtitleRegion *sr = GetRegionById(srr->RegionId())) {
a->x1 = int(round(FactorX * srr->RegionHorizontalAddress()));
a->y1 = int(round(FactorY * srr->RegionVerticalAddress()));
a->x2 = int(round(FactorX * (srr->RegionHorizontalAddress() + sr->RegionWidth() - 1)));
a->y2 = int(round(FactorY * (srr->RegionVerticalAddress() + sr->RegionHeight() - 1)));
a->x1 = srr->RegionHorizontalAddress();
a->y1 = srr->RegionVerticalAddress();
a->x2 = srr->RegionHorizontalAddress() + sr->RegionWidth() - 1;
a->y2 = srr->RegionVerticalAddress() + sr->RegionHeight() - 1;
a->bpp = sr->RegionDepth();
while ((a->Width() & 3) != 0)
a->x2++; // aligns width to a multiple of 4, so 2, 4 and 8 bpp will work
}
else
a->x1 = a->y1 = a->x2 = a->y2 = a->bpp = 0;
@ -1103,6 +1103,37 @@ tArea *cDvbSubtitlePage::GetAreas(int &NumAreas, double FactorX, double FactorY)
return NULL;
}
tArea cDvbSubtitlePage::CombineAreas(int NumAreas, const tArea *Areas)
{
tArea a;
a.x1 = INT_MAX;
a.x2 = INT_MIN;
a.y1 = INT_MAX;
a.y2 = INT_MIN;
a.bpp = 1;
for (int i = 0; i < NumAreas; i++) {
a.x1 = min(a.x1, Areas[i].x1);
a.x2 = max(a.x2, Areas[i].x2);
a.y1 = min(a.y1, Areas[i].y1);
a.y2 = max(a.y2, Areas[i].y2);
a.bpp = max(a.bpp, Areas[i].bpp);
}
return a;
}
tArea cDvbSubtitlePage::ScaleArea(const tArea &Area, double FactorX, double FactorY)
{
tArea a;
a.x1 = int(round(FactorX * Area.x1) );
a.x2 = int(round(FactorX * Area.x2) - 1);
a.y1 = int(round(FactorY * Area.y1) );
a.y2 = int(round(FactorY * Area.y2) - 1);
a.bpp = Area.bpp;
while ((a.Width() & 3) != 0)
a.x2++; // aligns width to a multiple of 4, so 2, 4 and 8 bpp will work
return a;
}
cSubtitleClut *cDvbSubtitlePage::GetClutById(int ClutId, bool New)
{
for (cSubtitleClut *sc = cluts.First(); sc; sc = cluts.Next(sc)) {
@ -1219,11 +1250,13 @@ private:
int timeout;
tArea *areas;
int numAreas;
tArea areaCombined;
tArea areaOsd;
double osdFactorX;
double osdFactorY;
cVector<cBitmap *> bitmaps;
public:
cDvbSubtitleBitmaps(int State, int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY);
cDvbSubtitleBitmaps(int State, int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY, tArea &AreaCombined, tArea &AreaOsd);
~cDvbSubtitleBitmaps();
int State(void) { return state; }
int64_t Pts(void) { return pts; }
@ -1234,13 +1267,15 @@ public:
void DbgDump(int WindowWidth, int WindowHeight);
};
cDvbSubtitleBitmaps::cDvbSubtitleBitmaps(int State, int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY)
cDvbSubtitleBitmaps::cDvbSubtitleBitmaps(int State, int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY, tArea &AreaCombined, tArea &AreaOsd)
{
state = State;
pts = Pts;
timeout = Timeout;
areas = Areas;
numAreas = NumAreas;
areaCombined = AreaCombined;
areaOsd = AreaOsd;
osdFactorX = OsdFactorX;
osdFactorY = OsdFactorY;
}
@ -1260,25 +1295,25 @@ void cDvbSubtitleBitmaps::AddBitmap(cBitmap *Bitmap)
void cDvbSubtitleBitmaps::Draw(cOsd *Osd)
{
bool Scale = !(DoubleEqual(osdFactorX, 1.0) && DoubleEqual(osdFactorY, 1.0));
bool AntiAlias = true;
bool AntiAlias = Setup.AntiAlias;
if (Scale && osdFactorX > 1.0 || osdFactorY > 1.0) {
// Upscaling requires 8bpp:
int Bpp[MAXOSDAREAS];
for (int i = 0; i < numAreas; i++) {
Bpp[i] = areas[i].bpp;
areas[i].bpp = 8;
}
if (Osd->CanHandleAreas(areas, numAreas) != oeOk) {
for (int i = 0; i < numAreas; i++)
areas[i].bpp = Bpp[i];
int Bpp = areaOsd.bpp;
areaOsd.bpp = 8;
if (Osd->CanHandleAreas(&areaOsd, 1) != oeOk) {
areaOsd.bpp = Bpp;
AntiAlias = false;
}
}
if (State() == 0 || Osd->SetAreas(areas, numAreas) == oeOk) {
if (State() == 0 || Osd->SetAreas(&areaOsd, 1) == oeOk) {
cBitmap combined(areaCombined.Width(), areaCombined.Height(), areaCombined.bpp);
combined.SetOffset(areaCombined.x1, areaCombined.y1);
for (int i = 0; i < bitmaps.Size(); i++) {
// merge bitmaps into combined
cBitmap *b = bitmaps[i];
Osd->DrawScaledBitmap(int(round(b->X0() * osdFactorX)), int(round(b->Y0() * osdFactorY)), *b, osdFactorX, osdFactorY, AntiAlias);
combined.DrawBitmap(b->X0(), b->Y0(), *b);
}
Osd->DrawScaledBitmap(int(round(combined.X0() * osdFactorX)), int(round(combined.Y0() * osdFactorY)), combined, osdFactorX, osdFactorY, AntiAlias);
Osd->Flush();
}
}
@ -1734,25 +1769,29 @@ void cDvbSubtitleConverter::FinishPage(cDvbSubtitlePage *Page)
if (!AssertOsd())
return;
int NumAreas;
tArea *Areas = Page->GetAreas(NumAreas, osdFactorX, osdFactorY);
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;
while (osd && osd->CanHandleAreas(Areas, NumAreas) != oeOk) {
dbgoutput("CanHandleAreas: %d<br>\n", osd->CanHandleAreas(Areas, NumAreas));
int HalfBpp = Bpp / 2;
if (HalfBpp >= 2) {
for (int i = 0; i < NumAreas; i++) {
if (Areas[i].bpp >= Bpp) {
Areas[i].bpp = HalfBpp;
if (osd) {
while (osd->CanHandleAreas(&AreaOsd, 1) != oeOk) {
dbgoutput("CanHandleAreas: %d<br>\n", osd->CanHandleAreas(&AreaOsd, 1));
int HalfBpp = Bpp / 2;
if (HalfBpp >= 2) {
if (AreaOsd.bpp >= Bpp) {
AreaOsd.bpp = HalfBpp;
Reduced = true;
}
}
Bpp = HalfBpp;
Bpp = HalfBpp;
}
else
return; // unable to draw bitmaps
}
else
return; // unable to draw bitmaps
}
cDvbSubtitleBitmaps *Bitmaps = new cDvbSubtitleBitmaps(Page->PageState(), Page->Pts(), Page->PageTimeout(), Areas, NumAreas, osdFactorX, osdFactorY);
}
cDvbSubtitleBitmaps *Bitmaps = new cDvbSubtitleBitmaps(Page->PageState(), Page->Pts(), Page->PageTimeout(), Areas, NumAreas, osdFactorX, osdFactorY, AreaCombined, AreaOsd);
bitmaps->Add(Bitmaps);
for (int i = 0; i < NumAreas; i++) {
if (cSubtitleRegionRef *srr = Page->GetRegionRefByIndex(i)) {

136
eit.c
View File

@ -8,9 +8,26 @@
* 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 4.10 2020/06/23 09:27:09 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:
// - Some use the same version for all tables, and use unique event ids, which are the same in
// both the 0x5X and the 0x6X tables. And once an event has an id, it keeps it until it is
// no longer in the tables. Those are the good guys!
// - Some use separate versions for each table (0x50, 0x51, ...).
// - Some broadcast tables 0x5X and 0x6X, but use different event ids for the same event in both
// sets of tables, and sometimes even use different titles, short texts or descriptions.
// - Some broadcast the full EPG only on one transponder (tables 0x6X), and on the actual transponder
// they provide only the present/following information.
// - Some have overlapping events, especially when they mess up daylight saving time.
// - Some use all new event ids every time they update their tables.
// So, to bring order to chaos, VDR does as follows:
// - Completely ignore table 0x4F.
// - 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.
#include "eit.h"
#include <sys/time.h>
#include "epg.h"
@ -22,25 +39,57 @@
#define DBGEIT 0
// --- cEitTables ------------------------------------------------------------
cEitTables::cEitTables(void)
{
complete = false;
tableStart = 0;
tableEnd = 0;
}
bool cEitTables::Check(uchar TableId, uchar Version, int SectionNumber)
{
int ti = Index(TableId);
return sectionSyncer[ti].Check(Version, SectionNumber);
}
bool cEitTables::Processed(uchar TableId, uchar LastTableId, int SectionNumber, int LastSectionNumber, int SegmentLastSectionNumber)
{
bool Result = false;
int ti = Index(TableId);
int LastIndex = Index(LastTableId);
complete = false;
if (sectionSyncer[ti].Processed(SectionNumber, LastSectionNumber, SegmentLastSectionNumber)) {
Result = true; // the table with TableId is complete
for (int i = 0; i <= LastIndex; i++) {
if (!sectionSyncer[i].Complete())
return Result;
}
complete = true; // all tables have been processed
}
return Result;
}
// --- cEIT ------------------------------------------------------------------
class cEIT : public SI::EIT {
public:
cEIT(cSectionSyncerHash &SectionSyncerHash, int Source, u_char Tid, const u_char *Data);
cEIT(cEitTablesHash &EitTablesHash, int Source, u_char Tid, const u_char *Data);
};
cEIT::cEIT(cSectionSyncerHash &SectionSyncerHash, int Source, u_char Tid, const u_char *Data)
cEIT::cEIT(cEitTablesHash &EitTablesHash, int Source, u_char Tid, const u_char *Data)
:SI::EIT(Data, false)
{
if (!CheckCRCAndParse())
return;
int HashId = Tid * getServiceId();
cSectionSyncerEntry *SectionSyncerEntry = SectionSyncerHash.Get(HashId);
if (!SectionSyncerEntry) {
SectionSyncerEntry = new cSectionSyncerEntry;
SectionSyncerHash.Add(SectionSyncerEntry, HashId);
int HashId = getServiceId();
cEitTables *EitTables = EitTablesHash.Get(HashId);
if (!EitTables) {
EitTables = new cEitTables;
EitTablesHash.Add(EitTables, HashId);
}
bool Process = SectionSyncerEntry->Sync(getVersionNumber(), getSectionNumber(), getLastSectionNumber());
bool Process = EitTables->Check(Tid, getVersionNumber(), getSectionNumber());
if (Tid != 0x4E && !Process) // we need to set the 'seen' tag to watch the running status of the present/following event
return;
@ -50,10 +99,8 @@ cEIT::cEIT(cSectionSyncerHash &SectionSyncerHash, int Source, u_char Tid, const
cStateKey ChannelsStateKey;
cChannels *Channels = cChannels::GetChannelsWrite(ChannelsStateKey, 10);
if (!Channels) {
SectionSyncerEntry->Repeat(); // let's not miss any section of the EIT
if (!Channels)
return;
}
tChannelID channelID(Source, getOriginalNetworkId(), getTransportStreamId(), getServiceId());
cChannel *Channel = Channels->GetByChannelID(channelID, true);
if (!Channel || EpgHandlers.IgnoreChannel(Channel)) {
@ -64,7 +111,14 @@ cEIT::cEIT(cSectionSyncerHash &SectionSyncerHash, int Source, u_char Tid, const
cStateKey SchedulesStateKey;
cSchedules *Schedules = cSchedules::GetSchedulesWrite(SchedulesStateKey, 10);
if (!Schedules) {
SectionSyncerEntry->Repeat(); // let's not miss any section of the EIT
ChannelsStateKey.Remove(false);
return;
}
cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(Channel, true);
if (pSchedule->OnActualTp(Tid) && (Tid & 0xF0) == 0x60) {
SchedulesStateKey.Remove(false);
ChannelsStateKey.Remove(false);
return;
}
@ -77,12 +131,11 @@ cEIT::cEIT(cSectionSyncerHash &SectionSyncerHash, int Source, u_char Tid, const
bool ChannelsModified = false;
bool handledExternally = EpgHandlers.HandledExternally(Channel);
cSchedule *pSchedule = (cSchedule *)Schedules->GetSchedule(Channel, true);
bool Empty = true;
bool Modified = false;
time_t LingerLimit = Now - Setup.EPGLinger * 60;
time_t SegmentStart = 0;
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 };
localtime_r(&Now, &t); // this initializes the time zone in 't'
@ -103,9 +156,19 @@ cEIT::cEIT(cSectionSyncerHash &SectionSyncerHash, int Source, u_char Tid, const
if (!SegmentStart)
SegmentStart = StartTime;
SegmentEnd = StartTime + Duration;
if (Tid == 0x4E) {
if (getSectionNumber() == 0)
EitTables->SetTableStart(SegmentStart);
else
EitTables->SetTableEnd(SegmentEnd);
}
cEvent *newEvent = NULL;
cEvent *rEvent = NULL;
cEvent *pEvent = (cEvent *)pSchedule->GetEvent(SiEitEvent.getEventId(), StartTime);
cEvent *pEvent = NULL;
if (Tid == 0x4E || (Tid & 0xF0) == 0x50)
pEvent = const_cast<cEvent *>(pSchedule->GetEventById(SiEitEvent.getEventId()));
else
pEvent = const_cast<cEvent *>(pSchedule->GetEventByTime(StartTime));
if (!pEvent || handledExternally) {
if (handledExternally && !EpgHandlers.IsUpdate(SiEitEvent.getEventId(), StartTime, Tid, getVersionNumber()))
continue;
@ -121,10 +184,13 @@ cEIT::cEIT(cSectionSyncerHash &SectionSyncerHash, int Source, u_char Tid, const
// We have found an existing event, either through its event ID or its start time.
pEvent->SetSeen();
uchar TableID = max(pEvent->TableID(), uchar(0x4E)); // for backwards compatibility, table ids less than 0x4E are treated as if they were "present"
// If the new event has a higher table ID, let's skip it.
// The lower the table ID, the more "current" the information.
if (Tid > TableID)
// We never overwrite present/following with events from other tables:
if (TableID == 0x4E && Tid != 0x4E)
continue;
if (pEvent->HasTimer()) {
if (pEvent->StartTime() != StartTime || pEvent->Duration() != Duration)
dsyslog("channel %d (%s) event %s times changed to %s-%s", Channel->Number(), Channel->Name(), *pEvent->ToDescr(), *TimeString(StartTime), *TimeString(StartTime + Duration));
}
EpgHandlers.SetEventID(pEvent, SiEitEvent.getEventId()); // unfortunately some stations use different event ids for the same event in different tables :-(
EpgHandlers.SetStartTime(pEvent, StartTime);
EpgHandlers.SetDuration(pEvent, Duration);
@ -256,7 +322,7 @@ cEIT::cEIT(cSectionSyncerHash &SectionSyncerHash, int Source, u_char Tid, const
cSchedule *rSchedule = (cSchedule *)Schedules->GetSchedule(tChannelID(Source, Channel->Nid(), Channel->Tid(), tsed->getReferenceServiceId()));
if (!rSchedule)
break;
rEvent = (cEvent *)rSchedule->GetEvent(tsed->getReferenceEventId());
rEvent = (cEvent *)rSchedule->GetEventById(tsed->getReferenceEventId());
if (!rEvent)
break;
EpgHandlers.SetTitle(pEvent, rEvent->Title());
@ -356,14 +422,20 @@ cEIT::cEIT(cSectionSyncerHash &SectionSyncerHash, int Source, u_char Tid, const
pSchedule->ClrRunningStatus(Channel);
pSchedule->SetPresentSeen();
}
if (Modified) {
EpgHandlers.SortSchedule(pSchedule);
EpgHandlers.DropOutdated(pSchedule, SegmentStart, SegmentEnd, Tid, getVersionNumber());
pSchedule->SetModified();
if (Process) {
bool Complete = EitTables->Processed(Tid, getLastTableId(), getSectionNumber(), getLastSectionNumber(), getSegmentLastSectionNumber());
if (Modified && (Tid >= 0x50 || Complete)) { // we process the 0x5X tables segment by segment, but 0x4E only if we have received ALL its segments (0 and 1, i.e. "present" and "following")
if (Tid == 0x4E && getLastSectionNumber() == 1) {
SegmentStart = EitTables->TableStart();
SegmentEnd = EitTables->TableEnd();
}
EpgHandlers.SortSchedule(pSchedule);
EpgHandlers.DropOutdated(pSchedule, SegmentStart, SegmentEnd, Tid, getVersionNumber());
}
}
EpgHandlers.EndSegmentTransfer(Modified);
SchedulesStateKey.Remove(Modified);
ChannelsStateKey.Remove(ChannelsModified);
EpgHandlers.EndSegmentTransfer(Modified);
}
// --- cTDT ------------------------------------------------------------------
@ -398,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");
}
@ -408,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");
}
@ -422,7 +494,7 @@ time_t cEitFilter::disableUntil = 0;
cEitFilter::cEitFilter(void)
{
Set(0x12, 0x40, 0xC0); // event info now&next actual/other TS (0x4E/0x4F), future actual/other TS (0x5X/0x6X)
Set(0x12, 0x40, 0xC0); // event info present&following actual/other TS (0x4E/0x4F), future actual/other TS (0x5X/0x6X)
Set(0x14, 0x70); // TDT
}
@ -430,7 +502,7 @@ void cEitFilter::SetStatus(bool On)
{
cMutexLock MutexLock(&mutex);
cFilter::SetStatus(On);
sectionSyncerHash.Clear();
eitTablesHash.Clear();
}
void cEitFilter::SetDisableUntil(time_t Time)
@ -449,8 +521,8 @@ void cEitFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
}
switch (Pid) {
case 0x12: {
if (Tid >= 0x4E && Tid <= 0x6F)
cEIT EIT(sectionSyncerHash, Source(), Tid, Data);
if (Tid == 0x4E || Tid >= 0x50 && Tid <= 0x6F) // we ignore 0x4F, which only causes trouble
cEIT EIT(eitTablesHash, Source(), Tid, Data);
}
break;
case 0x14: {

35
eit.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: eit.h 4.2 2017/05/08 21:10:29 kls Exp $
* $Id: eit.h 5.2 2021/04/04 11:06:30 kls Exp $
*/
#ifndef __EIT_H
@ -13,17 +13,42 @@
#include "filter.h"
#include "tools.h"
class cSectionSyncerEntry : public cListObject, public cSectionSyncer {};
#define NUM_EIT_TABLES 17
class cSectionSyncerHash : public cHash<cSectionSyncerEntry> {
// Event information (or EPG) is broadcast in tables 0x4E and 0x4F for "present/following" events on
// "this transponder" (0x4E) and "other transponders" (0x4F), as well as 0x50-0x5F ("all events on this
// transponder") and 0x60-0x6F ("all events on other transponders"). Since it's either "this" or "other",
// we only use one section syncer for 0x4E/0x4F and 16 syncers for either 0x5X or 0x6X.
class cEitTables : public cListObject {
private:
cSectionSyncerRandom sectionSyncer[NUM_EIT_TABLES]; // for tables 0x4E/0x4F and 0x50-0x5F/0x60-0x6F
time_t tableStart; // only used for table 0x4E
time_t tableEnd;
bool complete;
int Index(uchar TableId) { return (TableId < 0x50) ? 0 : (TableId & 0x0F) + 1; }
public:
cSectionSyncerHash(void) : cHash(HASHSIZE, true) {};
cEitTables(void);
void SetTableStart(time_t t) { tableStart = t; }
void SetTableEnd(time_t t) { tableEnd = t; }
time_t TableStart(void) { return tableStart; }
time_t TableEnd(void) { return tableEnd; }
bool Check(uchar TableId, uchar Version, int SectionNumber);
bool Processed(uchar TableId, uchar LastTableId, int SectionNumber, int LastSectionNumber, int SegmentLastSectionNumber = -1);
///< Returns true if all sections of the table with the given TableId have been processed.
bool Complete(void) { return complete; }
///< Returns true if all sections of all tables have been processed.
};
class cEitTablesHash : public cHash<cEitTables> {
public:
cEitTablesHash(void) : cHash(HASHSIZE, true) {};
};
class cEitFilter : public cFilter {
private:
cMutex mutex;
cSectionSyncerHash sectionSyncerHash;
cEitTablesHash eitTablesHash;
static time_t disableUntil;
protected:
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);

View File

@ -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();
}

View File

@ -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;

140
epg.c
View File

@ -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 4.9 2019/05/20 09:55:22 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,13 +544,13 @@ 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->GetEvent(EventID, StartTime);
Event = (cEvent *)Schedule->GetEventByTime(StartTime);
cEvent *newEvent = NULL;
if (Event)
DELETENULL(Event->components);
@ -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,8 +931,8 @@ cSchedule::cSchedule(tChannelID ChannelID)
channelID = ChannelID;
events.SetUseGarbageCollector();
numTimers = 0;
hasRunning = false;
modified = 0;
onActualTp = false;
presentSeen = 0;
}
@ -930,6 +950,13 @@ void cSchedule::DecNumTimers(void) const
numTimersMutex.Unlock();
}
bool cSchedule::OnActualTp(uchar TableId)
{
if ((TableId & 0xF0) == 0x50)
onActualTp = true;
return onActualTp;
}
cEvent *cSchedule::AddEvent(cEvent *Event)
{
events.Add(Event);
@ -942,15 +969,28 @@ void cSchedule::DelEvent(cEvent *Event)
{
if (Event->schedule == this) {
UnhashEvent(Event);
Event->schedule = NULL;
// Removing the event from its schedule prevents it from decrementing the
// schedule's timer counter, so we do it here:
cEvent::numTimersMutex.Lock();
numTimersMutex.Lock();
numTimers -= Event->numTimers;
numTimersMutex.Unlock();
cEvent::numTimersMutex.Unlock();
events.Del(Event);
}
}
void cSchedule::HashEvent(cEvent *Event)
{
if (cEvent *p = eventsHashID.Get(Event->EventID()))
eventsHashID.Del(p, p->EventID());
eventsHashID.Add(Event, Event->EventID());
if (Event->StartTime() > 0) // 'StartTime < 0' is apparently used with NVOD channels
if (Event->StartTime() > 0) { // 'StartTime < 0' is apparently used with NVOD channels
if (cEvent *p = eventsHashStartTime.Get(Event->StartTime()))
eventsHashStartTime.Del(p, p->StartTime());
eventsHashStartTime.Add(Event, Event->StartTime());
}
}
void cSchedule::UnhashEvent(cEvent *Event)
@ -990,14 +1030,16 @@ const cEvent *cSchedule::GetFollowingEvent(void) const
return p;
}
const cEvent *cSchedule::GetEvent(tEventID EventID, time_t StartTime) const
const cEvent *cSchedule::GetEventById(tEventID EventID) const
{
return eventsHashID.Get(EventID);
}
const cEvent *cSchedule::GetEventByTime(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);
return NULL;
}
const cEvent *cSchedule::GetEventAround(time_t Time) const
@ -1016,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) {
@ -1026,23 +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;
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)
@ -1054,29 +1091,23 @@ 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();
}
void cSchedule::DropOutdated(time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version)
{
// Events are sorted by start time.
if (SegmentStart > 0 && SegmentEnd > 0) {
cEvent *p = events.First();
while (p) {
cEvent *n = events.Next(p);
if (p->EndTime() > SegmentStart) {
if (p->StartTime() >= SegmentStart) {
if (p->StartTime() < SegmentEnd) {
// The event overlaps with the given time segment.
if (p->TableID() > TableID || p->TableID() == TableID && p->Version() != Version) {
// The segment overwrites all events from tables with higher ids, and
// The event starts within the given time segment.
if ((p->TableID() > 0x4E || TableID == 0x4E) && (p->TableID() != TableID || p->Version() != Version)) {
// The segment overwrites all events from tables with other ids, and
// within the same table id all events must have the same version.
// Special consideration: table 0x4E can only be overwritten with the same id!
DelEvent(p);
}
}
@ -1086,6 +1117,20 @@ void cSchedule::DropOutdated(time_t SegmentStart, time_t SegmentEnd, uchar Table
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)
@ -1097,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;
@ -1311,8 +1356,13 @@ bool cSchedules::Read(FILE *f)
fclose(f);
if (result) {
// Initialize the channels' schedule pointers, so that the first WhatsOn menu will come up faster:
for (cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel))
for (cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) {
if (const cSchedule *Schedule = Channel->schedule) {
if (!Schedule->ChannelID().Valid()) // this is the DummySchedule
Channel->schedule = NULL;
}
Schedules->GetSchedule(Channel);
}
}
return result;
}
@ -1342,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());

13
epg.h
View File

@ -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 4.7 2017/05/28 12:59:20 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,13 +157,14 @@ 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;
public:
cSchedule(tChannelID ChannelID);
tChannelID ChannelID(void) const { return channelID; }
bool Modified(int &State) const { bool Result = State != modified; State = modified; return Result; }
bool OnActualTp(uchar TableId);
time_t PresentSeen(void) const { return presentSeen; }
bool PresentSeenWithin(int Seconds) const { return time(NULL) - presentSeen < Seconds; }
void SetModified(void) { modified++; }
@ -183,7 +186,8 @@ public:
const cList<cEvent> *Events(void) const { return &events; }
const cEvent *GetPresentEvent(void) const;
const cEvent *GetFollowingEvent(void) const;
const cEvent *GetEvent(tEventID EventID, time_t StartTime = 0) const;
const cEvent *GetEventById(tEventID EventID) const;
const cEvent *GetEventByTime(time_t StartTime) const;
const cEvent *GetEventAround(time_t Time) const;
void Dump(const cChannels *Channels, FILE *f, const char *Prefix = "", eDumpMode DumpMode = dmAll, time_t AtTime = 0) const;
static bool Read(FILE *f, cSchedules *Schedules);
@ -265,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; }
@ -289,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.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: filter.c 4.3 2017/05/09 08:37:23 kls Exp $
* $Id: filter.c 5.2 2024/10/13 09:47:18 kls Exp $
*/
#include "filter.h"
@ -12,8 +12,9 @@
// --- cSectionSyncer --------------------------------------------------------
cSectionSyncer::cSectionSyncer(void)
cSectionSyncer::cSectionSyncer(bool Random)
{
random = Random;
Reset();
}
@ -23,34 +24,53 @@ void cSectionSyncer::Reset(void)
currentSection = -1;
synced = false;
complete = false;
segments = 0;
memset(sections, 0x00, sizeof(sections));
}
void cSectionSyncer::Repeat(void)
{
SetSectionFlag(currentSection, false);
synced = false;
complete = false;
}
bool cSectionSyncer::Sync(uchar Version, int Number, int LastNumber)
bool cSectionSyncer::Check(uchar Version, int SectionNumber)
{
if (Version != currentVersion) {
Reset();
currentVersion = Version;
}
if (!synced) {
if (Number != 0)
if (complete)
return false;
if (!random) {
if (!synced) {
if (SectionNumber == 0) {
currentSection = 0;
synced = true;
}
else
return false;
}
if (SectionNumber != currentSection)
return false;
else
synced = true;
}
currentSection = Number;
bool Result = !GetSectionFlag(Number);
SetSectionFlag(Number, true);
if (Number == LastNumber)
complete = true;
return Result;
return !GetSectionFlag(SectionNumber);
}
bool cSectionSyncer::Processed(int SectionNumber, int LastSectionNumber, int SegmentLastSectionNumber)
{
SetSectionFlag(SectionNumber, true); // the flag for this section
if (!random)
currentSection++; // expect the next section
int Index = SectionNumber / 8; // the segment (byte) in which this section lies
uchar b = 0xFF; // all sections in this segment
if (SegmentLastSectionNumber < 0 && Index == LastSectionNumber / 8)
SegmentLastSectionNumber = LastSectionNumber;
if (SegmentLastSectionNumber >= 0) {
b >>= 7 - (SegmentLastSectionNumber & 0x07); // limits them up to the last section in this segment
if (!random && SectionNumber == SegmentLastSectionNumber)
currentSection = (SectionNumber + 8) & ~0x07; // expect first section of next segment
}
if (sections[Index] == b) // all expected sections in this segment have been received
segments |= 1 << Index; // so we set the respective bit in the segments flags
uint32_t s = 0xFFFFFFFF; // all segments
s >>= 31 - (LastSectionNumber / 8); // limits them up to the last expected segment
complete = segments == s;
return complete;
}
// --- cFilterData -----------------------------------------------------------

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: filter.h 4.3 2017/05/09 08:37:23 kls Exp $
* $Id: filter.h 5.5 2024/10/13 09:47:18 kls Exp $
*/
#ifndef __FILTER_H
@ -17,17 +17,42 @@ class cSectionSyncer {
private:
int currentVersion;
int currentSection;
bool random;
bool synced;
bool complete;
uint32_t segments; // bit flags for the 32 segments
uchar sections[32]; // holds 32 * 8 = 256 bits, as flags for the sections
void SetSectionFlag(uchar Section, bool On) { if (On) sections[Section / 8] |= (1 << (Section % 8)); else sections[Section / 8] &= ~(1 << (Section % 8)); }
bool GetSectionFlag(uchar Section) { return sections[Section / 8] & (1 << (Section % 8)); }
public:
cSectionSyncer(void);
cSectionSyncer(bool Random = false);
///< Sets up a new section syncer.
///< Call Check() to see whether a given section needs processing. Once the section
///< has been processed, call Processed() to mark it as such. If, for any reason,
///< processing is not completed after calling Check(), nothing special needs to be
///< done. Just don't call Processed() and a later call to Check() with the same
///< SectionNumber will return true again.
///< If Random is true, sections can be processed in random order, not necessarily
///< starting with section 0.
void Reset(void);
void Repeat(void);
bool Check(uchar Version, int SectionNumber);
///< Returns true if Version is not the current version, or the given SectionNumber has not
///< been marked as processed, yet. Sections are handled in ascending order, starting at 0,
///< unless Random is true in the constructor call.
bool Processed(int SectionNumber, int LastSectionNumber, int SegmentLastSectionNumber = -1);
///< Marks the given SectionNumber as processed.
///< LastSectionNumber is used to determine whether all sections have been processed.
///< SegmentLastSectionNumber can be given to handle partially filled segments (like,
///< for instance in the EIT).
///< Returns true if all sections have been processed.
bool Complete(void) { return complete; }
bool Sync(uchar Version, int Number, int LastNumber);
///< Returns true if all sections have been processed.
};
class cSectionSyncerRandom : public cSectionSyncer {
///< Helper class for having an array of random section syncers.
public:
cSectionSyncerRandom(void): cSectionSyncer(true) {}
};
class cFilterData : public cListObject {

11
font.c
View File

@ -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
View File

@ -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)") },

View File

@ -6,7 +6,7 @@
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* $Id: descriptor.c 4.3 2020/06/23 09:27:09 kls Exp $
* $Id: descriptor.c 4.4 2020/12/17 12:52:57 kls Exp $
* *
***************************************************************************/
@ -94,6 +94,7 @@ char *ExtendedEventDescriptors::getText(char *buffer, int size, const char *sepa
char tmpbuf[tmpsize];
const char *fromCode = NULL;
int index=0, len;
*tmpbuf = 0; // just in case length is 0
for (int i=0;i<length;i++) {
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
if (!d)

View File

@ -6,7 +6,7 @@
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* $Id: si.c 4.2 2020/05/15 11:31:40 kls Exp $
* $Id: si.c 4.3 2020/12/19 14:41:41 kls Exp $
* *
***************************************************************************/
@ -413,6 +413,7 @@ static int Utf8CharLen(const char *s)
size_t convertCharacterTable(const char *from, size_t fromLength, char *to, size_t toLength, const char *fromCode)
{
bool converted = false;
char *result = to;
if (SystemCharacterTable && fromCode) {
iconv_t cd = iconv_open(SystemCharacterTable, fromCode);
@ -433,9 +434,10 @@ size_t convertCharacterTable(const char *from, size_t fromLength, char *to, size
}
*to = 0;
iconv_close(cd);
converted = true;
}
}
else {
if (!converted) {
size_t len = fromLength;
if (len >= toLength)
len = toLength - 1;

View File

@ -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,

Some files were not shown because too many files have changed in this diff Show More