diff --git a/0001-Fix-build-with-systemd-230.patch b/0001-Fix-build-with-systemd-230.patch deleted file mode 100644 index f96210f..0000000 --- a/0001-Fix-build-with-systemd-230.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0376d2e4adc38528c0cbdde759a56700bee95872 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ville=20Skytt=C3=A4?= -Date: Fri, 17 Jun 2016 17:08:31 +0300 -Subject: [PATCH] Fix build with systemd >= 230 - -libsystemd-daemon has been merged to libsystemd. ---- - Makefile | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/Makefile b/Makefile -index b90cbd2..9193cde 100644 ---- a/Makefile -+++ b/Makefile -@@ -95,9 +95,9 @@ DEFINES += -DBIDI - LIBS += $(shell pkg-config --libs fribidi) - endif - ifdef SDNOTIFY --INCLUDES += $(shell pkg-config --cflags libsystemd-daemon) -+INCLUDES += $(shell pkg-config --silence-errors --cflags libsystemd-daemon || pkg-config --cflags libsystemd) - DEFINES += -DSDNOTIFY --LIBS += $(shell pkg-config --libs libsystemd-daemon) -+LIBS += $(shell pkg-config --silence-errors --libs libsystemd-daemon || pkg-config --libs libsystemd) - endif - - LIRC_DEVICE ?= /var/run/lirc/lircd --- -2.5.5 - diff --git a/dvbhdffdevice.patch b/dvbhdffdevice.patch deleted file mode 100644 index af751df..0000000 --- a/dvbhdffdevice.patch +++ /dev/null @@ -1,12 +0,0 @@ ---- dvbhddevice/dvbhdffdevice.c.orig 2018-04-17 13:57:26.871268867 +0200 -+++ dvbhddevice/dvbhdffdevice.c 2018-04-17 13:58:45.698264299 +0200 -@@ -461,7 +461,8 @@ - const tTrackId *TrackId = GetTrack(Type); - if (TrackId && TrackId->id) { - int streamType = 0; -- cChannel * channel = Channels.GetByNumber(CurrentChannel()); -+ LOCK_CHANNELS_READ; -+ const cChannel * channel = Channels->GetByNumber(CurrentChannel()); - if (channel) { - if (IS_AUDIO_TRACK(Type)) - streamType = channel->Atype(Type - ttAudioFirst); diff --git a/missing-kernel-headers.patch b/missing-kernel-headers.patch deleted file mode 100644 index 2a8e225..0000000 --- a/missing-kernel-headers.patch +++ /dev/null @@ -1,66 +0,0 @@ -diff -Naur vdr-2.4.7/PLUGINS/src/dvbhddevice/dvbhdffdevice.c vdr-2.4.7-new/PLUGINS/src/dvbhddevice/dvbhdffdevice.c ---- vdr-2.4.7/PLUGINS/src/dvbhddevice/dvbhdffdevice.c 2018-04-20 22:23:47.000000000 +0200 -+++ vdr-2.4.7-new/PLUGINS/src/dvbhddevice/dvbhdffdevice.c 2021-08-03 14:22:36.172626332 +0200 -@@ -11,9 +11,9 @@ - #include - #include - #include --#include -+#include <../kernel-headers-5.13/audio.h> - #include --#include -+#include <../kernel-headers-5.13/video.h> - #include - #include - #include -diff -Naur vdr-2.4.7/PLUGINS/src/dvbhddevice/hdffosd.c vdr-2.4.7-new/PLUGINS/src/dvbhddevice/hdffosd.c ---- vdr-2.4.7/PLUGINS/src/dvbhddevice/hdffosd.c 2018-04-20 22:23:47.000000000 +0200 -+++ vdr-2.4.7-new/PLUGINS/src/dvbhddevice/hdffosd.c 2021-08-03 14:22:36.177626332 +0200 -@@ -5,7 +5,7 @@ - */ - - #include "hdffosd.h" --#include -+#include <../kernel-headers-5.13/osd.h> - #include - #include - #include "hdffcmd.h" -diff -Naur vdr-2.4.7/PLUGINS/src/dvbhddevice/dvbsdffosd.c vdr-2.4.7-new/PLUGINS/src/dvbhddevice/dvbsdffosd.c ---- vdr-2.4.7/PLUGINS/src/dvbsddevice/dvbsdffosd.c 2011-04-17 14:55:09.000000000 +0200 -+++ vdr-2.4.7-new/PLUGINS/src/dvbsddevice/dvbsdffosd.c 2021-08-03 14:22:36.188626333 +0200 -@@ -7,7 +7,7 @@ - */ - - #include "dvbsdffosd.h" --#include -+#include <../kernel-headers-5.13/osd.h> - #include - #include - #include -diff -Naur vdr-2.4.7/PLUGINS/src/dvbhddevice/libhdffcmd/hdffcmd_base.h vdr-2.4.7-new/PLUGINS/src/dvbhddevice/libhdffcmd/hdffcmd_base.h ---- vdr-2.4.7/PLUGINS/src/dvbhddevice/libhdffcmd/hdffcmd_base.h 2018-04-20 22:23:47.000000000 +0200 -+++ vdr-2.4.7-new/PLUGINS/src/dvbhddevice/libhdffcmd/hdffcmd_base.h 2021-08-03 14:22:36.193626333 +0200 -@@ -24,7 +24,7 @@ - #ifndef HDFFCMD_BASE_H - #define HDFFCMD_BASE_H - --#include -+#include <../kernel-headers-5.13/osd.h> - - #if !defined OSD_RAW_CMD - typedef struct osd_raw_cmd_s { -diff -Naur vdr-2.4.7/PLUGINS/src/dvbsddevice/dvbsdffdevice.c vdr-2.4.7-new/PLUGINS/src/dvbsddevice/dvbsdffdevice.c ---- vdr-2.4.7/PLUGINS/src/dvbsddevice/dvbsdffdevice.c 2014-03-15 13:35:21.000000000 +0100 -+++ vdr-2.4.7-new/PLUGINS/src/dvbsddevice/dvbsdffdevice.c 2021-08-03 14:22:36.203626334 +0200 -@@ -10,9 +10,9 @@ - #include - #include - #include --#include -+#include <../kernel-headers-5.13/audio.h> - #include --#include -+#include <../kernel-headers-5.13/video.h> - #include - #include - #include diff --git a/opt-42-x_MainMenuHooks-v1.0.3.patch b/opt-42-x_MainMenuHooks-v1.0.3.patch deleted file mode 100644 index 150f96b..0000000 --- a/opt-42-x_MainMenuHooks-v1.0.3.patch +++ /dev/null @@ -1,188 +0,0 @@ -Description: This patch allows plugins to replace the VDR mainmenus "Schedule", "Channels", "Timers" and "Recordings" by a different implementation. -Author: Frank Schmirler -This is a "patch" for the Video Disk Recorder (VDR). - -* History -2012-04-06: Version 1.0.2 -- Update für aktuelle VDR-Entwickler-Versionen (Manuel Reimer) - -2010-10-15: Version 1.0.1 -- return a cOsdObject instead of its subclass cOsdMenu (thanks to - Joe_D@vdrportal) -- version number defines in config.h now follow the ususal conventions: - MAINMENUHOOKSVERSNUM is now a number, the newly added define - MAINMENUHOOKSVERSION is a string (suggested by gnapheus@vdrportal) -- patch is now based on VDR 1.6.0 -- updated documentation - -2007-02-26: Version 1.0 -- Initial revision. - -* Authors: -Tobias Grimm -Martin Prochnow -Frank Schmirler -Christian Wieninger - -* Description: -This patch allows plugins to replace the VDR mainmenus "Schedule", -"Channels", "Timers" and "Recordings" by a different implementation. - -The patch is based on a suggestion of Christian Wieninger back in 2006 -(http://www.linuxtv.org/pipermail/vdr/2006-March/008234.html). It is -meant to be an interim solution for VDR 1.4 until (maybe) VDR 1.5 -introduces an official API for this purpose. - -* Installation -Change into the VDR source directory, then issue - patch -p1 < path/to/MainMenuHooks-v1_0_1.patch -and recompile. - -* Notes for plugin authors -The following code sample shows the required plugin code for replacing -the original Schedule menu: - -bool cMyPlugin::Service(const char *Id, void *Data) -{ - cOsdMenu **menu = (cOsdMenu**) Data; - if (MySetup.replaceSchedule && - strcmp(Id, "MainMenuHooksPatch-v1.0::osSchedule") == 0) { - if (menu) - *menu = (cOsdMenu*) MainMenuAction(); - return true; - } - return false; -} - -Since patch version 1.0.1 the service call may return a cOsdObject -instead of a cOsdMenu. Use "#ifdef MAINMENUHOOKSVERSION" to detect -version 1.0.1. - -A plugin can replace more than one menu at a time. Simply replace the -call to MainMenuAction() in the sample above by appropriate code. - -Note that a plugin *should* offer a setup option which allows the user -to enable or disable the replacement. "Disabled" would be a reasonable -default setting. By testing for define MAINMENUHOOKSVERSNUM, a plugin -can leave the setup option out at compiletime. - -In case there is an internal problem when trying to open the replacement -menu, it is safe to return true even though Data is NULL. However an -OSD message should indicate the problem to the user. - -Feel free to ship this patch along with your plugin. However if you -think you need to modify the patch, we'd encourage you to contact the -authors first or at least use a service id which differs in more than -just the version number. - -Index: b/menu.c -=================================================================== ---- a/menu.c -+++ b/menu.c -@@ -4620,15 +4620,31 @@ - - // Initial submenus: - -+ cOsdObject *menu = NULL; - switch (State) { -- case osSchedule: AddSubMenu(new cMenuSchedule); break; -- case osChannels: AddSubMenu(new cMenuChannels); break; -- case osTimers: AddSubMenu(new cMenuTimers); break; -- case osRecordings: AddSubMenu(new cMenuRecordings(NULL, 0, OpenSubMenus)); break; -- case osSetup: AddSubMenu(new cMenuSetup); break; -- case osCommands: AddSubMenu(new cMenuCommands(tr("Commands"), &Commands)); break; -+ case osSchedule: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu)) -+ menu = new cMenuSchedule; -+ break; -+ case osChannels: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu)) -+ menu = new cMenuChannels; -+ break; -+ case osTimers: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu)) -+ menu = new cMenuTimers; -+ break; -+ case osRecordings: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu)) -+ menu = new cMenuRecordings(NULL, 0, true); -+ break; -+ case osSetup: menu = new cMenuSetup; break; -+ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break; - default: break; - } -+ if (menu) -+ if (menu->IsMenu()) -+ AddSubMenu((cOsdMenu *) menu); - } - - cOsdObject *cMenuMain::PluginOsdObject(void) -@@ -4765,13 +4781,34 @@ - eOSState state = cOsdMenu::ProcessKey(Key); - HadSubMenu |= HasSubMenu(); - -+ cOsdObject *menu = NULL; - switch (state) { -- case osSchedule: return AddSubMenu(new cMenuSchedule); -- case osChannels: return AddSubMenu(new cMenuChannels); -- case osTimers: return AddSubMenu(new cMenuTimers); -- case osRecordings: return AddSubMenu(new cMenuRecordings); -- case osSetup: return AddSubMenu(new cMenuSetup); -- case osCommands: return AddSubMenu(new cMenuCommands(tr("Commands"), &Commands)); -+ case osSchedule: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu)) -+ menu = new cMenuSchedule; -+ else -+ state = osContinue; -+ break; -+ case osChannels: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu)) -+ menu = new cMenuChannels; -+ else -+ state = osContinue; -+ break; -+ case osTimers: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu)) -+ menu = new cMenuTimers; -+ else -+ state = osContinue; -+ break; -+ case osRecordings: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu)) -+ menu = new cMenuRecordings; -+ else -+ state = osContinue; -+ break; -+ case osSetup: menu = new cMenuSetup; break; -+ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break; - case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) { - if (cOsdItem *item = Get(Current())) { - cRecordControls::Stop(item->Text() + strlen(tr(STOP_RECORDING))); -@@ -4857,6 +4894,12 @@ - default: break; - } - } -+ if (menu) { -+ if (menu->IsMenu()) -+ return AddSubMenu((cOsdMenu *) menu); -+ pluginOsdObject = menu; -+ return osPlugin; -+ } - if (!HasSubMenu() && Update(HadSubMenu)) - Display(); - if (Key != kNone) { -Index: b/config.h -=================================================================== ---- a/config.h -+++ b/config.h -@@ -36,6 +36,10 @@ - // plugins to work with newer versions of the core VDR as long as no - // VDR header files have changed. - -+// The MainMenuHook Patch's version number: -+#define MAINMENUHOOKSVERSION "1.0.1" -+#define MAINMENUHOOKSVERSNUM 10001 // Version * 10000 + Major * 100 + Minor -+ - #define MAXPRIORITY 99 - #define MINPRIORITY (-MAXPRIORITY) - #define LIVEPRIORITY 0 // priority used when selecting a device for live viewing diff --git a/skincurses-log-errors.patch b/skincurses-log-errors.patch deleted file mode 100644 index 0a43729..0000000 --- a/skincurses-log-errors.patch +++ /dev/null @@ -1,21 +0,0 @@ -Description: Log an error message when skincures can't initialize the screen -Author: Tobias Grimm - ---- a/PLUGINS/src/skincurses/skincurses.c -+++ b/PLUGINS/src/skincurses/skincurses.c -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - - static const char *VERSION = "2.4.0"; - static const char *DESCRIPTION = trNOOP("A text only skin"); -@@ -833,6 +834,7 @@ - ScOsdHeight = w->_maxy - w->_begy + 1; - return true; - } -+ esyslog("skincurses: unable to initialize curses screen"); - return false; - } - diff --git a/vdr-1.5.17-progressbar-support-0.0.1.diff b/vdr-1.5.17-progressbar-support-0.0.1.diff deleted file mode 100644 index 98b887d..0000000 --- a/vdr-1.5.17-progressbar-support-0.0.1.diff +++ /dev/null @@ -1,106 +0,0 @@ -diff -Nru vdr-1.5.17-orig/skinclassic.c vdr-1.5.17-progressbar/skinclassic.c ---- vdr-1.5.17-orig/skinclassic.c -+++ vdr-1.5.17-progressbar/skinclassic.c -@@ -314,8 +314,47 @@ - for (int i = 0; i < MaxTabs; i++) { - const char *s = GetTabbedText(Text, i); - if (s) { -- int xt = x0 + Tab(i); -- osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x2 - xt); -+ bool isprogressbar = false; -+ int now = 0, total = 0; -+ // check if progress bar: "[||||||| ]" -+ if ((strlen(s) > 5 && s[0] == '[' && s[strlen(s) - 1] == ']')) { -+ const char *p = s + 1; -+ // update status -+ isprogressbar = true; -+ for (; *p != ']'; ++p) { -+ // check if progressbar characters -+ if (*p == ' ' || *p == '|') { -+ // update counters -+ ++total; -+ if (*p == '|') -+ ++now; -+ } -+ else { -+ // wrong character detected; not a progressbar -+ isprogressbar = false; -+ break; -+ } -+ } -+ } -+ int xt = x0 + Tab(i); -+ if (isprogressbar) { -+ // define x coordinates of progressbar -+ int px0 = xt; -+ int px1 = (Tab(i + 1)?Tab(i+1):x1) - 5; -+ int px = px0 + max((int)((float) now * (float) (px1 - px0) / (float) total), 1); -+ // define y coordinates of progressbar -+ int py0 = y + 4; -+ int py1 = y + lineHeight - 4; -+ // draw background -+ osd->DrawRectangle(px0, y, (Tab(i + 1)?Tab(i+1):x1) - 1, y + lineHeight - 1, ColorBg); -+ // draw progressbar -+ osd->DrawRectangle(px0, py0, px, py1, ColorFg); -+ osd->DrawRectangle(px + 1, py0, px1, py0 + 1, ColorFg); -+ osd->DrawRectangle(px + 1, py1 - 1, px1, py1, ColorFg); -+ osd->DrawRectangle(px1 - 1, py0, px1, py1, ColorFg); -+ } -+ else -+ osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x2 - xt); - } - if (!Tab(i + 1)) - break; -diff -Nru vdr-1.5.17-orig/skinsttng.c vdr-1.5.17-progressbar/skinsttng.c ---- vdr-1.5.17-orig/skinsttng.c -+++ vdr-1.5.17-progressbar/skinsttng.c -@@ -558,8 +558,47 @@ - for (int i = 0; i < MaxTabs; i++) { - const char *s = GetTabbedText(Text, i); - if (s) { -- int xt = x3 + 5 + Tab(i); -- osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x4 - xt); -+ bool isprogressbar = false; -+ int now = 0, total = 0; -+ // check if progress bar: "[||||||| ]" -+ if ((strlen(s) > 5 && s[0] == '[' && s[strlen(s) - 1] == ']')) { -+ const char *p = s + 1; -+ // update status -+ isprogressbar = true; -+ for (; *p != ']'; ++p) { -+ // check if progressbar characters -+ if (*p == ' ' || *p == '|') { -+ // update counters -+ ++total; -+ if (*p == '|') -+ ++now; -+ } -+ else { -+ // wrong character detected; not a progressbar -+ isprogressbar = false; -+ break; -+ } -+ } -+ } -+ int xt = x3 + 5 + Tab(i); -+ if (isprogressbar) { -+ // define x coordinates of progressbar -+ int px0 = xt; -+ int px1 = x3 + (Tab(i + 1)?Tab(i + 1):x4-x3-5) - 1; -+ int px = px0 + max((int)((float) now * (float) (px1 - px0) / (float) total), 1); -+ // define y coordinates of progressbar -+ int py0 = y + 4; -+ int py1 = y + lineHeight - 4; -+ // draw background -+ osd->DrawRectangle(px0, y, (Tab(i + 1)?Tab(i + 1):x4-x3-5) - 1, y + lineHeight - 1, ColorBg); -+ // draw progressbar -+ osd->DrawRectangle(px0, py0, px, py1, ColorFg); -+ osd->DrawRectangle(px + 1, py0, px1, py0 + 1, ColorFg); -+ osd->DrawRectangle(px + 1, py1 - 1, px1, py1, ColorFg); -+ osd->DrawRectangle(px1 - 1, py0, px1, py1, ColorFg); -+ } -+ else -+ osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x4 - xt); - } - if (!Tab(i + 1)) - break; diff --git a/vdr-1.5.18-syncearly.patch b/vdr-1.5.18-syncearly.patch deleted file mode 100644 index de06ca8..0000000 --- a/vdr-1.5.18-syncearly.patch +++ /dev/null @@ -1,114 +0,0 @@ -Sync early parts extracted from the non-dvbs2 patch at -http://article.gmane.org/gmane.linux.vdr/36097, fprintf(stderr) calls -changed to dsyslog(). - -diff -Nurp ../vdr-1.5.18-orig/device.c ./device.c ---- ../vdr-1.5.18-orig/device.c 2008-03-09 11:03:34.000000000 +0100 -+++ ./device.c 2008-03-19 22:34:40.000000000 +0100 -@@ -840,7 +840,7 @@ eSetChannelResult cDevice::SetChannel(co - } - for (int i = 0; i < MAXSPIDS; i++) - SetAvailableTrack(ttSubtitle, i, Channel->Spid(i), Channel->Slang(i)); -- if (!NeedsTransferMode) -+ if (!NeedsTransferMode || GetCurrentAudioTrack() == ttNone) - EnsureAudioTrack(true); - EnsureSubtitleTrack(); - } -diff -Nurp ../vdr-1.5.18-orig/remux.c ./remux.c ---- ../vdr-1.5.18-orig/remux.c 2007-11-25 14:56:03.000000000 +0100 -+++ ./remux.c 2008-02-24 19:47:40.000000000 +0100 -@@ -1896,12 +2526,13 @@ int cRingBufferLinearPes::DataReady(cons - - #define RESULTBUFFERSIZE KILOBYTE(256) - --cRemux::cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure) -+cRemux::cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure, bool SyncEarly) - { - exitOnFailure = ExitOnFailure; - noVideo = VPid == 0 || VPid == 1 || VPid == 0x1FFF; - numUPTerrors = 0; - synced = false; -+ syncEarly = SyncEarly; - skipped = 0; - numTracks = 0; - resultSkipped = 0; -@@ -2105,12 +2840,14 @@ uchar *cRemux::Get(int &Count, uchar *Pi - } - } - else if (!synced) { -- if (pt == I_FRAME) { -+ if (pt == I_FRAME || syncEarly) { - if (PictureType) - *PictureType = pt; - resultSkipped = i; // will drop everything before this position -- SetBrokenLink(data + i, l); - synced = true; -+ if (pt == I_FRAME) // syncEarly: it's ok but there is no need to call SetBrokenLink() -+ SetBrokenLink(data + i, l); -+else dsyslog("video: synced early"); - } - } - else if (Count) -@@ -2123,17 +2860,19 @@ uchar *cRemux::Get(int &Count, uchar *Pi - l = GetPacketLength(data, resultCount, i); - if (l < 0) - return resultData; -- if (noVideo) { -+ if (noVideo || !synced && syncEarly) { -+ uchar pt = NO_PICTURE; - if (!synced) { -- if (PictureType) -- *PictureType = I_FRAME; -+ if (PictureType && noVideo) -+ *PictureType = pt; - resultSkipped = i; // will drop everything before this position - synced = true; -+if (!noVideo) dsyslog("audio: synced early"); - } - else if (Count) - return resultData; - else if (PictureType) -- *PictureType = I_FRAME; -+ *PictureType = pt; - } - } - if (synced) { -diff -Nurp ../vdr-1.5.18-orig/remux.h ./remux.h ---- ../vdr-1.5.18-orig/remux.h 2007-09-02 12:19:06.000000000 +0200 -+++ ./remux.h 2008-02-24 19:47:40.000000000 +0100 -@@ -40,6 +40,7 @@ - bool noVideo; - int numUPTerrors; - bool synced; -+ bool syncEarly; - int skipped; - cTS2PES *ts2pes[MAXTRACKS]; - int numTracks; -@@ -47,12 +48,13 @@ - int resultSkipped; - int GetPid(const uchar *Data); - public: -- cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure = false); -+ cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure = false, bool SyncEarly = false); - ///< Creates a new remuxer for the given PIDs. VPid is the video PID, while - ///< APids, DPids and SPids are pointers to zero terminated lists of audio, - ///< dolby and subtitle PIDs (the pointers may be NULL if there is no such - ///< PID). If ExitOnFailure is true, the remuxer will initiate an "emergency -- ///< exit" in case of problems with the data stream. -+ ///< exit" in case of problems with the data stream. SyncEarly causes cRemux -+ ///< to sync as soon as a video or audio frame is seen. - ~cRemux(); - void SetTimeouts(int PutTimeout, int GetTimeout) { resultBuffer->SetTimeouts(PutTimeout, GetTimeout); } - ///< By default cRemux assumes that Put() and Get() are called from different -diff -Nurp ../vdr-1.5.18-orig/transfer.c ./transfer.c ---- ../vdr-1.5.18-orig/transfer.c 2007-01-05 11:45:28.000000000 +0100 -+++ ./transfer.c 2008-02-24 19:47:40.000000000 +0100 -@@ -19,7 +19,7 @@ cTransfer::cTransfer(tChannelID ChannelI - ,cThread("transfer") - { - ringBuffer = new cRingBufferLinear(TRANSFERBUFSIZE, TS_SIZE * 2, true, "Transfer"); -- remux = new cRemux(VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids); -+ remux = new cRemux(VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids, false, true); - } - - cTransfer::~cTransfer() diff --git a/vdr-1.7.21-timercmd.patch b/vdr-1.7.21-timercmd.patch deleted file mode 100644 index 8d31543..0000000 --- a/vdr-1.7.21-timercmd.patch +++ /dev/null @@ -1,107 +0,0 @@ -diff -up vdr-1.7.21/config.c~ vdr-1.7.21/config.c ---- vdr-1.7.21/config.c~ 2011-10-18 00:02:51.394223695 +0300 -+++ vdr-1.7.21/config.c 2011-10-18 00:12:30.255855027 +0300 -@@ -211,6 +211,7 @@ bool cNestedItemList::Save(void) - cNestedItemList Folders; - cNestedItemList Commands; - cNestedItemList RecordingCommands; -+cNestedItemList TimerCommands; - - // --- cSVDRPhosts ----------------------------------------------------------- - -diff -up vdr-1.7.21/config.h~ vdr-1.7.21/config.h ---- vdr-1.7.21/config.h~ 2011-10-18 00:02:51.438227770 +0300 -+++ vdr-1.7.21/config.h 2011-10-18 00:12:30.702896536 +0300 -@@ -187,6 +187,7 @@ public: - extern cNestedItemList Folders; - extern cNestedItemList Commands; - extern cNestedItemList RecordingCommands; -+extern cNestedItemList TimerCommands; - extern cSVDRPhosts SVDRPhosts; - - class cSetupLine : public cListObject { -diff -up vdr-1.7.21/menu.c~ vdr-1.7.21/menu.c ---- vdr-1.7.21/menu.c~ 2011-10-18 00:02:51.428226843 +0300 -+++ vdr-1.7.21/menu.c 2011-10-18 00:12:29.520786768 +0300 -@@ -1142,6 +1142,7 @@ void cTimerEntry::SetDiskStatus(char Dis - - class cMenuTimers : public cOsdMenu { - private: -+ eOSState Commands(eKeys Key = kNone); - int helpKeys; - eOSState Edit(void); - eOSState New(void); -@@ -1259,6 +1260,53 @@ eOSState cMenuTimers::Delete(void) - return osContinue; - } - -+#define CHECK_2PTR_NULL(x_,y_) ((x_)? ((y_)? y_:""):"") -+ -+eOSState cMenuTimers::Commands(eKeys Key) -+{ -+ if (HasSubMenu() || Count() == 0) -+ return osContinue; -+ cTimer *ti = CurrentTimer(); -+ if (ti) { -+ char *parameter = NULL; -+ const cEvent *pEvent = ti->Event(); -+ int iRecNumber=0; -+ -+ if(!pEvent) { -+ Timers.SetEvents(); -+ pEvent = ti->Event(); -+ } -+ if(pEvent) { -+// create a dummy recording to get the real filename -+ cRecording *rc_dummy = new cRecording(ti, pEvent); -+ Recordings.Load(); -+ cRecording *rc = Recordings.GetByName(rc_dummy->FileName()); -+ -+ delete rc_dummy; -+ if(rc) -+ iRecNumber=rc->Index() + 1; -+ } -+//Parameter format TimerNumber 'ChannelId' Start Stop 'Titel' 'Subtitel' 'file' RecNumer -+// 1 2 3 4 5 6 7 8 -+ asprintf(¶meter, "%d '%s' %d %d '%s' '%s' '%s' %d", ti->Index(), -+ *ti->Channel()->GetChannelID().ToString(), -+ (int)ti->StartTime(), -+ (int)ti->StopTime(), -+ CHECK_2PTR_NULL(pEvent, pEvent->Title()), -+ CHECK_2PTR_NULL(pEvent, pEvent->ShortText()), -+ ti->File(), -+ iRecNumber); -+ isyslog("timercmd: %s", parameter); -+ cMenuCommands *menu; -+ eOSState state = AddSubMenu(menu = new cMenuCommands(tr("Timer commands"), &TimerCommands, parameter)); -+ free(parameter); -+ if (Key != kNone) -+ state = menu->ProcessKey(Key); -+ return state; -+ } -+ return osContinue; -+} -+ - eOSState cMenuTimers::Info(void) - { - if (HasSubMenu() || Count() == 0) -@@ -1346,6 +1394,8 @@ eOSState cMenuTimers::ProcessKey(eKeys K - case kInfo: - case kBlue: return Info(); - break; -+ case k1...k9: return Commands(Key); -+ case k0: return (TimerCommands.Count()? Commands():osContinue); - default: break; - } - } -diff -up vdr-1.7.21/vdr.c~ vdr-1.7.21/vdr.c ---- vdr-1.7.21/vdr.c~ 2011-10-18 00:02:51.284213503 +0300 -+++ vdr-1.7.21/vdr.c 2011-10-18 00:12:31.901007794 +0300 -@@ -602,6 +602,7 @@ int main(int argc, char *argv[]) - Timers.Load(AddDirectory(ConfigDirectory, "timers.conf")); - Commands.Load(AddDirectory(ConfigDirectory, "commands.conf")); - RecordingCommands.Load(AddDirectory(ConfigDirectory, "reccmds.conf")); -+ TimerCommands.Load(AddDirectory(ConfigDirectory, "timercmds.conf")); - SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true); - Keys.Load(AddDirectory(ConfigDirectory, "remote.conf")); - KeyMacros.Load(AddDirectory(ConfigDirectory, "keymacros.conf"), true); diff --git a/vdr-1.7.29-hlcutter-0.2.3.diff b/vdr-1.7.29-hlcutter-0.2.3.diff deleted file mode 100644 index 776a278..0000000 --- a/vdr-1.7.29-hlcutter-0.2.3.diff +++ /dev/null @@ -1,612 +0,0 @@ -diff -Naur vdr-1.7.27/config.c vdr-1.7.27-hlcutter/config.c ---- vdr-1.7.27/config.c 2012-02-29 11:15:54.000000000 +0100 -+++ vdr-1.7.27-hlcutter/config.c 2012-03-31 13:25:56.000000000 +0200 -@@ -445,8 +445,10 @@ - FontSmlSize = 18; - FontFixSize = 20; - MaxVideoFileSize = MAXVIDEOFILESIZEDEFAULT; -+ MaxRecordingSize = DEFAULTRECORDINGSIZE; - SplitEditedFiles = 0; - DelTimeshiftRec = 0; -+ HardLinkCutter = 0; - MinEventTimeout = 30; - MinUserInactivity = 300; - NextWakeupTime = 0; -@@ -639,8 +641,10 @@ - else if (!strcasecmp(Name, "FontSmlSize")) FontSmlSize = atoi(Value); - else if (!strcasecmp(Name, "FontFixSize")) FontFixSize = atoi(Value); - else if (!strcasecmp(Name, "MaxVideoFileSize")) MaxVideoFileSize = atoi(Value); -+ else if (!strcasecmp(Name, "MaxRecordingSize")) MaxRecordingSize = atoi(Value); - else if (!strcasecmp(Name, "SplitEditedFiles")) SplitEditedFiles = atoi(Value); - else if (!strcasecmp(Name, "DelTimeshiftRec")) DelTimeshiftRec = atoi(Value); -+ else if (!strcasecmp(Name, "HardLinkCutter")) HardLinkCutter = atoi(Value); - else if (!strcasecmp(Name, "MinEventTimeout")) MinEventTimeout = atoi(Value); - else if (!strcasecmp(Name, "MinUserInactivity")) MinUserInactivity = atoi(Value); - else if (!strcasecmp(Name, "NextWakeupTime")) NextWakeupTime = atoi(Value); -@@ -736,8 +740,10 @@ - Store("FontSmlSize", FontSmlSize); - Store("FontFixSize", FontFixSize); - Store("MaxVideoFileSize", MaxVideoFileSize); -+ Store("MaxRecordingSize", MaxRecordingSize); - Store("SplitEditedFiles", SplitEditedFiles); - Store("DelTimeshiftRec", DelTimeshiftRec); -+ Store("HardLinkCutter", HardLinkCutter); - Store("MinEventTimeout", MinEventTimeout); - Store("MinUserInactivity", MinUserInactivity); - Store("NextWakeupTime", NextWakeupTime); -diff -Naur vdr-1.7.27/config.h vdr-1.7.27-hlcutter/config.h ---- vdr-1.7.27/config.h 2012-03-11 11:41:44.000000000 +0100 -+++ vdr-1.7.27-hlcutter/config.h 2012-03-31 13:25:56.000000000 +0200 -@@ -299,8 +299,10 @@ - int FontSmlSize; - int FontFixSize; - int MaxVideoFileSize; -+ int MaxRecordingSize; - int SplitEditedFiles; - int DelTimeshiftRec; -+ int HardLinkCutter; - int MinEventTimeout, MinUserInactivity; - time_t NextWakeupTime; - int MultiSpeedMode; -diff -Naur vdr-1.7.27/cutter.c vdr-1.7.27-hlcutter/cutter.c ---- vdr-1.7.27/cutter.c 2012-02-16 13:08:39.000000000 +0100 -+++ vdr-1.7.27-hlcutter/cutter.c 2012-03-31 13:26:51.000000000 +0200 -@@ -80,6 +80,7 @@ - Mark = fromMarks.Next(Mark); - off_t FileSize = 0; - int CurrentFileNumber = 0; -+ bool SkipThisSourceFile = false; - int LastIFrame = 0; - toMarks.Add(0); - toMarks.Save(); -@@ -98,13 +99,93 @@ - - // Read one frame: - -- if (fromIndex->Get(Index++, &FileNumber, &FileOffset, &Independent, &Length)) { -- if (FileNumber != CurrentFileNumber) { -- fromFile = fromFileName->SetOffset(FileNumber, FileOffset); -- if (fromFile) -- fromFile->SetReadAhead(MEGABYTE(20)); -- CurrentFileNumber = FileNumber; -- } -+ if (!fromIndex->Get(Index++, &FileNumber, &FileOffset, &Independent, &Length)) { -+ // Error, unless we're past last cut-in and there's no cut-out -+ if (Mark || LastMark) -+ error = "index"; -+ break; -+ } -+ -+ if (FileNumber != CurrentFileNumber) { -+ fromFile = fromFileName->SetOffset(FileNumber, FileOffset); -+ if (fromFile) -+ fromFile->SetReadAhead(MEGABYTE(20)); -+ CurrentFileNumber = FileNumber; -+ if (SkipThisSourceFile) { -+ // At end of fast forward: Always skip to next file -+ toFile = toFileName->NextFile(); -+ if (!toFile) { -+ error = "toFile 4"; -+ break; -+ } -+ FileSize = 0; -+ SkipThisSourceFile = false; -+ } -+ -+ -+ if (Setup.HardLinkCutter && FileOffset == 0) { -+ // We are at the beginning of a new source file. -+ // Do we need to copy the whole file? -+ -+ // if !Mark && LastMark, then we're past the last cut-out and continue to next I-frame -+ // if !Mark && !LastMark, then there's just a cut-in, but no cut-out -+ // if Mark, then we're between a cut-in and a cut-out -+ -+ uint16_t MarkFileNumber; -+ off_t MarkFileOffset; -+ // Get file number of next cut mark -+ if (!Mark && !LastMark -+ || Mark -+ && fromIndex->Get(Mark->Position(), &MarkFileNumber, &MarkFileOffset) -+ && (MarkFileNumber != CurrentFileNumber)) { -+ // The current source file will be copied completely. -+ // Start new output file unless we did that already -+ if (FileSize != 0) { -+ toFile = toFileName->NextFile(); -+ if (!toFile) { -+ error = "toFile 3"; -+ break; -+ } -+ FileSize = 0; -+ } -+ -+ // Safety check that file has zero size -+ struct stat buf; -+ if (stat(toFileName->Name(), &buf) == 0) { -+ if (buf.st_size != 0) { -+ esyslog("cCuttingThread: File %s exists and has nonzero size", toFileName->Name()); -+ error = "nonzero file exist"; -+ break; -+ } -+ } -+ else if (errno != ENOENT) { -+ esyslog("cCuttingThread: stat failed on %s", toFileName->Name()); -+ error = "stat"; -+ break; -+ } -+ -+ // Clean the existing 0-byte file -+ toFileName->Close(); -+ cString ActualToFileName(ReadLink(toFileName->Name()), true); -+ unlink(ActualToFileName); -+ unlink(toFileName->Name()); -+ -+ // Try to create a hard link -+ if (HardLinkVideoFile(fromFileName->Name(), toFileName->Name())) { -+ // Success. Skip all data transfer for this file -+ SkipThisSourceFile = true; -+ cutIn = false; -+ toFile = NULL; // was deleted by toFileName->Close() -+ } -+ else { -+ // Fallback: Re-open the file if necessary -+ toFile = toFileName->Open(); -+ } -+ } -+ } -+ } -+ -+ if (!SkipThisSourceFile) { - if (fromFile) { - int len = ReadFrame(fromFile, buffer, Length, sizeof(buffer)); - if (len < 0) { -@@ -121,19 +202,12 @@ - break; - } - } -- else { -- // Error, unless we're past the last cut-in and there's no cut-out -- if (Mark || LastMark) -- error = "index"; -- break; -- } -- - // Write one frame: - - if (Independent) { // every file shall start with an independent frame - if (LastMark) // edited version shall end before next I-frame - break; -- if (FileSize > maxVideoFileSize) { -+ if (!SkipThisSourceFile && FileSize > toFileName->MaxFileSize()) { - toFile = toFileName->NextFile(); - if (!toFile) { - error = "toFile 1"; -@@ -143,7 +217,7 @@ - } - CheckForSeamlessStream = false; - } -- if (cutIn) { -+ if (!SkipThisSourceFile && cutIn) { - if (isPesRecording) - cRemux::SetBrokenLink(buffer, Length); - else -@@ -151,7 +225,7 @@ - cutIn = false; - } - } -- if (toFile->Write(buffer, Length) < 0) { -+ if (!SkipThisSourceFile && toFile->Write(buffer, Length) < 0) { - error = "safe_write"; - break; - } -@@ -186,7 +260,7 @@ - } - } - else -- LastMark = true; -+ LastMark = true; // After last cut-out: Write on until next I-frame, then exit - } - } - Recordings.TouchUpdate(); -diff -Naur vdr-1.7.27/menu.c vdr-1.7.27-hlcutter/menu.c ---- vdr-1.7.27/menu.c 2012-03-13 14:14:38.000000000 +0100 -+++ vdr-1.7.27-hlcutter/menu.c 2012-03-31 13:25:56.000000000 +0200 -@@ -3116,8 +3116,10 @@ - Add(new cMenuEditStrItem( tr("Setup.Recording$Name instant recording"), data.NameInstantRecord, sizeof(data.NameInstantRecord))); - Add(new cMenuEditIntItem( tr("Setup.Recording$Instant rec. time (min)"), &data.InstantRecordTime, 1, MAXINSTANTRECTIME)); - Add(new cMenuEditIntItem( tr("Setup.Recording$Max. video file size (MB)"), &data.MaxVideoFileSize, MINVIDEOFILESIZE, MAXVIDEOFILESIZETS)); -+ Add(new cMenuEditIntItem( tr("Setup.Recording$Max. recording size (GB)"), &data.MaxRecordingSize, MINRECORDINGSIZE, MAXRECORDINGSIZE)); - Add(new cMenuEditBoolItem(tr("Setup.Recording$Split edited files"), &data.SplitEditedFiles)); - Add(new cMenuEditStraItem(tr("Setup.Recording$Delete timeshift recording"),&data.DelTimeshiftRec, 3, delTimeshiftRecTexts)); -+ Add(new cMenuEditBoolItem(tr("Setup.Recording$Hard Link Cutter"), &data.HardLinkCutter)); - } - - // --- cMenuSetupReplay ------------------------------------------------------ -diff -Naur vdr-1.7.27/po/de_DE.po vdr-1.7.27-hlcutter/po/de_DE.po ---- vdr-1.7.27/po/de_DE.po 2012-03-11 11:44:44.000000000 +0100 -+++ vdr-1.7.27-hlcutter/po/de_DE.po 2012-03-31 13:36:31.000000000 +0200 -@@ -1071,12 +1071,18 @@ - msgid "Setup.Recording$Max. video file size (MB)" - msgstr "Max. Videodateigröße (MB)" - -+msgid "Setup.Recording$Max. recording size (GB)" -+msgstr "Max. Aufnahmegröße (GB)" -+ - msgid "Setup.Recording$Split edited files" - msgstr "Editierte Dateien aufteilen" - - msgid "Setup.Recording$Delete timeshift recording" - msgstr "Zeitversetzte Aufnahme löschen" - -+msgid "Setup.Recording$Hard Link Cutter" -+msgstr "Hard Link Cutter" -+ - msgid "Replay" - msgstr "Wiedergabe" - -diff -Naur vdr-1.7.27/po/fi_FI.po vdr-1.7.27-hlcutter/po/fi_FI.po ---- vdr-1.7.27/po/fi_FI.po 2012-03-11 11:44:43.000000000 +0100 -+++ vdr-1.7.27-hlcutter/po/fi_FI.po 2012-03-31 13:39:33.000000000 +0200 -@@ -1074,12 +1074,18 @@ - msgid "Setup.Recording$Max. video file size (MB)" - msgstr "Suurin tiedostokoko (Mt)" - -+msgid "Setup.Recording$Max. recording size (GB)" -+msgstr "Suurin tallennekoko (Gt)" -+ - msgid "Setup.Recording$Split edited files" - msgstr "Jaottele muokatut tallenteet" - - msgid "Setup.Recording$Delete timeshift recording" - msgstr "Poista ajansiirtotallenne" - -+msgid "Setup.Recording$Hard Link Cutter" -+msgstr "Käytä kovia linkkejä muokkauksessa" -+ - msgid "Replay" - msgstr "Toisto" - -diff -Naur vdr-1.7.27/README-HLCUTTER vdr-1.7.27-hlcutter/README-HLCUTTER ---- vdr-1.7.27/README-HLCUTTER 1970-01-01 01:00:00.000000000 +0100 -+++ vdr-1.7.27-hlcutter/README-HLCUTTER 2012-03-31 13:40:55.000000000 +0200 -@@ -0,0 +1,128 @@ -+ -+ VDR-HLCUTTER README -+ -+ -+Written by: Udo Richter -+Available at: http://www.udo-richter.de/vdr/patches.html#hlcutter -+ http://www.udo-richter.de/vdr/patches.en.html#hlcutter -+Contact: udo_richter@gmx.de -+ -+ -+ -+About -+----- -+ -+The hard link cutter patch changes the recording editing algorithms of VDR to -+use filesystem hard links to 'copy' recording files whenever possible to speed -+up editing recordings noticeably. -+ -+The patch has matured to be quite stable, at least I'm using it without issues. -+Nevertheless the patch is still in development and should be used with caution. -+The patch is EXPERIMENTAL for multiple /videoxx folders. The safety checks -+should prevent data loss, but you should always carefully check the results. -+ -+While editing a recording, the patch searches for any 00x.vdr files that don't -+contain editing marks and would normally be copied 1:1 unmodified to the edited -+recording. In this case the current target 00x.vdr file will be aborted, and -+the cutter process attempts to duplicate the source file as a hard link, so -+that both files share the same disk space. If this succeeds, the editing -+process fast-forwards through the duplicated file and continues normally -+beginning with the next source file. If hard linking fails, the cutter process -+continues with plain old copying. (but does not take up the aborted last file.) -+ -+After editing, the un-edited recording can be deleted as usual, the hard linked -+copies will continue to exist as the only remaining copy. -+ -+To be effective, the default 'Max. video file size (MB)' should be lowered. -+The patch lowers the smallest possible file size to 1mb. Since VDR only -+supports up to 255 files, this would limit the recording size to 255Mb or -+10 minutes, in other words: This setting is insane! -+ -+To make sure that the 255 file limit will not be reached, the patch also -+introduces "Max. recording size (GB)" with a default of 100Gb (66 hours), and -+increases the file size to 2000Mb early enough, so that 100Gb-recordings will -+fit into the 255 files. -+ -+Picking the right parameters can be tricky. The smaller the file size, the -+faster the editing process works. However, with a small file size, long -+recordings will fall back to 2000Mb files soon, that are slow on editing again. -+ -+Here are some examples: -+ -+Max file size: 100Gb 100Gb 100Gb 100Gb 100Gb 100Gb 100Gb -+Max recording size: 1Mb 10Mb 20Mb 30Mb 40Mb 50Mb 100Mb -+ -+Small files: 1-203 1-204 1-205 1-206 1-207 1-209 1-214 -+ GBytes: 0.2 2.0 4.0 6.0 8.1 10.2 20.9 -+ Hours: 0.13 1.3 2.65 4 5.4 6.8 13.9 -+ -+Big (2000mb) files: 204-255 204-255 206-255 207-255 208-255 210-255 215-255 -+ GBytes: 101.5 99.6 97.7 95.7 93.8 89.8 80.1 -+ Hours: 67 66 65 63 62 60 53 -+ -+A recording limit of 100Gb keeps plenty of reserve without blocking too much -+file numbers. And with a file size of 30-40Mb, recordings of 4-5 hours fit into -+small files completely. (depends on bit rate of course) -+ -+ -+ -+The patch must be enabled in Setup-> Recordings-> Hard Link Cutter. When -+disabled, the cutter process behaves identical to VDR's default cutter. -+ -+There's a //#define HARDLINK_TEST_ONLY in the videodir.c file that enables a -+test-mode that hard-links 00x.vdr_ files only, and continues the classic -+editing. The resulting 00x.vdr and 00x.vdr_ files should be identical. If you -+delete the un-edited recording, don't forget to delete the *.vdr_ files too, -+they will now eat real disk space. -+ -+Note: 'du' displays the disk space of hard links only on first appearance, and -+usually you will see a noticeably smaller size on the edited recording. -+ -+ -+History -+------- -+ -+Version 0.2.3 -+ Fix: Compatible to VDR-1.7.27+ thx to Ville Skyttä -+ New: Add German translation -+ New: Add Finnish translation, thx to Ville Skyttä -+ -+Version 0.2.2 -+ Fix: Adapt to GCC-4.4, thx to Ville Skyttä -+ -+Version 0.2.1 -+ New: Support for TS recordings with up to 65535 files and up to 1TB per file -+ -+Version 0.2.0 -+ New: Support for multiple /videoXX recording folders, using advanced searching -+ for matching file systems where a hard link can be created. -+ Also supports deep mounted file systems. -+ Fix: Do not fail if last mark is a cut-in. (Again.) -+ -+Version 0.1.4 -+ New: Dynamic increase of file size before running out of xxx.vdr files -+ Fix: Last edit mark is not a cut-out -+ Fix: Write error if link-copied file is smaller than allowed file size -+ Fix: Broken index/marks if cut-in is at the start of a new file -+ Fix: Clear dangling pointer to free'd cUnbufferedFile, -+ thx to Matthias Schwarzott -+ -+Version 0.1.0 -+ Initial release -+ -+ -+ -+ -+Future plans -+------------ -+ -+Since original and edited copy share disk space, free space is wrong if one of -+them is moved to *.del. Free space should only count files with hard link -+count = 1. This still goes wrong if all copies get deleted. -+ -+ -+For more safety, the hard-linked files may be made read-only, as modifications -+to one copy will affect the other copy too. (except deleting, of course) -+ -+ -+SetBrokenLink may get lost on rare cases, this needs some more thoughts. -diff -Naur vdr-1.7.27/recorder.c vdr-1.7.27-hlcutter/recorder.c ---- vdr-1.7.27/recorder.c 2011-09-04 11:26:44.000000000 +0200 -+++ vdr-1.7.27-hlcutter/recorder.c 2012-03-31 13:25:56.000000000 +0200 -@@ -89,7 +89,7 @@ - bool cRecorder::NextFile(void) - { - if (recordFile && frameDetector->IndependentFrame()) { // every file shall start with an independent frame -- if (fileSize > MEGABYTE(off_t(Setup.MaxVideoFileSize)) || RunningLowOnDiskSpace()) { -+ if (fileSize > fileName->MaxFileSize() || RunningLowOnDiskSpace()) { - recordFile = fileName->NextFile(); - fileSize = 0; - } -diff -Naur vdr-1.7.27/recording.c vdr-1.7.27-hlcutter/recording.c ---- vdr-1.7.27/recording.c 2012-03-13 14:17:57.000000000 +0100 -+++ vdr-1.7.27-hlcutter/recording.c 2012-03-31 13:25:56.000000000 +0200 -@@ -2064,6 +2064,20 @@ - return NULL; - } - -+off_t cFileName::MaxFileSize() { -+ const int maxVideoFileSize = isPesRecording ? MAXVIDEOFILESIZEPES : MAXVIDEOFILESIZETS; -+ const int setupMaxVideoFileSize = min(maxVideoFileSize, Setup.MaxVideoFileSize); -+ const int maxFileNumber = isPesRecording ? 255 : 65535; -+ -+ const off_t smallFiles = (maxFileNumber * off_t(maxVideoFileSize) - 1024 * Setup.MaxRecordingSize) -+ / max(maxVideoFileSize - setupMaxVideoFileSize, 1); -+ -+ if (fileNumber <= smallFiles) -+ return MEGABYTE(off_t(setupMaxVideoFileSize)); -+ -+ return MEGABYTE(off_t(maxVideoFileSize)); -+} -+ - cUnbufferedFile *cFileName::NextFile(void) - { - return SetOffset(fileNumber + 1); -diff -Naur vdr-1.7.27/recording.h vdr-1.7.27-hlcutter/recording.h ---- vdr-1.7.27/recording.h 2012-03-13 13:41:05.000000000 +0100 -+++ vdr-1.7.27-hlcutter/recording.h 2012-03-31 13:25:56.000000000 +0200 -@@ -264,9 +264,17 @@ - // before the next independent frame, to have a complete Group Of Pictures): - #define MAXVIDEOFILESIZETS 1048570 // MB - #define MAXVIDEOFILESIZEPES 2000 // MB --#define MINVIDEOFILESIZE 100 // MB -+#define MINVIDEOFILESIZE 1 // MB - #define MAXVIDEOFILESIZEDEFAULT MAXVIDEOFILESIZEPES - -+#define MINRECORDINGSIZE 25 // GB -+#define MAXRECORDINGSIZE 500 // GB -+#define DEFAULTRECORDINGSIZE 100 // GB -+// Dynamic recording size: -+// Keep recording file size at Setup.MaxVideoFileSize for as long as possible, -+// but switch to MAXVIDEOFILESIZE early enough, so that Setup.MaxRecordingSize -+// will be reached, before recording to file 65535.vdr -+ - struct tIndexTs; - class cIndexFileGenerator; - -@@ -319,6 +327,8 @@ - cUnbufferedFile *Open(void); - void Close(void); - cUnbufferedFile *SetOffset(int Number, off_t Offset = 0); // yes, Number is int for easier internal calculating -+ off_t MaxFileSize(); -+ // Dynamic file size for this file - cUnbufferedFile *NextFile(void); - }; - -diff -Naur vdr-1.7.27/videodir.c vdr-1.7.27-hlcutter/videodir.c ---- vdr-1.7.27/videodir.c 2008-02-16 14:00:03.000000000 +0100 -+++ vdr-1.7.27-hlcutter/videodir.c 2012-03-31 13:25:56.000000000 +0200 -@@ -19,6 +19,9 @@ - #include "recording.h" - #include "tools.h" - -+ -+//#define HARDLINK_TEST_ONLY -+ - const char *VideoDirectory = VIDEODIR; - - class cVideoDirectory { -@@ -168,6 +171,120 @@ - return RemoveFileOrDir(FileName, true); - } - -+static bool StatNearestDir(const char *FileName, struct stat *Stat) -+{ -+ cString Name(FileName); -+ char *p; -+ while ((p = strrchr((char*)(const char*)Name + 1, '/')) != NULL) { -+ *p = 0; // truncate at last '/' -+ if (stat(Name, Stat) == 0) { -+ isyslog("StatNearestDir: Stating %s", (const char*)Name); -+ return true; -+ } -+ } -+ return false; -+} -+ -+bool HardLinkVideoFile(const char *OldName, const char *NewName) -+{ -+ // Incoming name must be in base video directory: -+ if (strstr(OldName, VideoDirectory) != OldName) { -+ esyslog("ERROR: %s not in %s", OldName, VideoDirectory); -+ return false; -+ } -+ if (strstr(NewName, VideoDirectory) != NewName) { -+ esyslog("ERROR: %s not in %s", NewName, VideoDirectory); -+ return false; -+ } -+ -+ const char *ActualNewName = NewName; -+ cString ActualOldName(ReadLink(OldName), true); -+ -+ // Some safety checks: -+ struct stat StatOldName; -+ if (lstat(ActualOldName, &StatOldName) == 0) { -+ if (S_ISLNK(StatOldName.st_mode)) { -+ esyslog("HardLinkVideoFile: Failed to resolve symbolic link %s", (const char*)ActualOldName); -+ return false; -+ } -+ } -+ else { -+ esyslog("HardLinkVideoFile: lstat failed on %s", (const char*)ActualOldName); -+ return false; -+ } -+ isyslog("HardLinkVideoFile: %s is on %i", (const char*)ActualOldName, (int)StatOldName.st_dev); -+ -+ // Find the video directory where ActualOldName is located -+ -+ cVideoDirectory Dir; -+ struct stat StatDir; -+ if (!StatNearestDir(NewName, &StatDir)) { -+ esyslog("HardLinkVideoFile: stat failed on %s", NewName); -+ return false; -+ } -+ -+ isyslog("HardLinkVideoFile: %s is on %i", NewName, (int)StatDir.st_dev); -+ if (StatDir.st_dev != StatOldName.st_dev) { -+ // Not yet found. -+ -+ if (!Dir.IsDistributed()) { -+ esyslog("HardLinkVideoFile: No matching video folder to hard link %s", (const char*)ActualOldName); -+ return false; -+ } -+ -+ // Search in video01 and upwards -+ bool found = false; -+ while (Dir.Next()) { -+ Dir.Store(); -+ const char *TmpNewName = Dir.Adjust(NewName); -+ if (StatNearestDir(TmpNewName, &StatDir) && StatDir.st_dev == StatOldName.st_dev) { -+ isyslog("HardLinkVideoFile: %s is on %i (match)", TmpNewName, (int)StatDir.st_dev); -+ ActualNewName = TmpNewName; -+ found = true; -+ break; -+ } -+ isyslog("HardLinkVideoFile: %s is on %i", TmpNewName, (int)StatDir.st_dev); -+ } -+ if (ActualNewName == NewName) { -+ esyslog("HardLinkVideoFile: No matching video folder to hard link %s", (const char*)ActualOldName); -+ return false; -+ } -+ -+ // Looking good, we have a match. Create necessary folders. -+ if (!MakeDirs(ActualNewName, false)) -+ return false; -+ // There's no guarantee that the directory of ActualNewName -+ // is on the same device as the dir that StatNearestDir found. -+ // But worst case is that the link fails. -+ } -+ -+#ifdef HARDLINK_TEST_ONLY -+ // Do the hard link to *.vdr_ for testing only -+ char *name = NULL; -+ asprintf(&name, "%s_",ActualNewName); -+ link(ActualOldName, name); -+ free(name); -+ return false; -+#endif // HARDLINK_TEST_ONLY -+ -+ // Try creating the hard link -+ if (link(ActualOldName, ActualNewName) != 0) { -+ // Failed to hard link. Maybe not allowed on file system. -+ LOG_ERROR_STR(ActualNewName); -+ isyslog("HardLinkVideoFile: failed to hard link from %s to %s", (const char*)ActualOldName, ActualNewName); -+ return false; -+ } -+ -+ if (ActualNewName != NewName) { -+ // video01 and up. Do the remaining symlink -+ if (symlink(ActualNewName, NewName) < 0) { -+ LOG_ERROR_STR(NewName); -+ return false; -+ } -+ } -+ return true; -+} -+ - bool VideoFileSpaceAvailable(int SizeMB) - { - cVideoDirectory Dir; -diff -Naur vdr-1.7.27/videodir.h vdr-1.7.27-hlcutter/videodir.h ---- vdr-1.7.27/videodir.h 2008-02-16 13:53:11.000000000 +0100 -+++ vdr-1.7.27-hlcutter/videodir.h 2012-03-31 13:25:56.000000000 +0200 -@@ -19,6 +19,7 @@ - int CloseVideoFile(cUnbufferedFile *File); - bool RenameVideoFile(const char *OldName, const char *NewName); - bool RemoveVideoFile(const char *FileName); -+bool HardLinkVideoFile(const char *OldName, const char *NewName); - bool VideoFileSpaceAvailable(int SizeMB); - int VideoDiskSpace(int *FreeMB = NULL, int *UsedMB = NULL); // returns the used disk space in percent - cString PrefixVideoFileName(const char *FileName, char Prefix); diff --git a/vdr-1.7.41-paths.patch b/vdr-1.7.41-paths.patch deleted file mode 100644 index 742c291..0000000 --- a/vdr-1.7.41-paths.patch +++ /dev/null @@ -1,84 +0,0 @@ -diff -up vdr-1.7.41/epg2html~ vdr-1.7.41/epg2html ---- vdr-1.7.41/epg2html~ 2013-03-04 15:02:20.000000000 +0200 -+++ vdr-1.7.41/epg2html 2013-03-16 19:08:17.467701640 +0200 -@@ -2,12 +2,12 @@ - - # A simple EPG to HTML converter - # --# Converts the EPG data written by 'vdr' into the file /video/epg.data -+# Converts the EPG data written by 'vdr' into the file __CACHEDIR__/epg.data - # into a simple HTML programme listing, consisting of one file per channel - # plus an 'index.htm' file. All output files are written into the current - # directory. - # --# Usage: epg2html < /video/epg.data -+# Usage: epg2html < __CACHEDIR__/epg.data - # - # See the main source file 'vdr.c' for copyright information and - # how to reach the author. -diff -up vdr-1.7.41/newplugin~ vdr-1.7.41/newplugin ---- vdr-1.7.41/newplugin~ 2013-01-12 15:46:00.000000000 +0200 -+++ vdr-1.7.41/newplugin 2013-03-16 19:08:18.140713300 +0200 -@@ -24,7 +24,7 @@ $PLUGIN_VERSION = "0.0.1"; - $PLUGIN_DESCRIPTION = "Enter description for '$PLUGIN_NAME' plugin"; - $PLUGIN_MAINENTRY = $PLUGIN_CLASS; - --$PLUGINS_SRC = "PLUGINS/src"; -+$PLUGINS_SRC = "."; - - $README = qq - {This is a "plugin" for the Video Disk Recorder (VDR). -diff -up vdr-1.7.41/vdr.1~ vdr-1.7.41/vdr.1 ---- vdr-1.7.41/vdr.1~ 2013-03-15 12:44:54.000000000 +0200 -+++ vdr-1.7.41/vdr.1 2013-03-16 19:08:16.621686914 +0200 -@@ -51,7 +51,7 @@ Save cache files in \fIdir\fR - .TP - .BI \-c\ dir ,\ \-\-config= dir - Read config files from directory \fIdir\fR --(default is to read them from the video directory). -+(default is to read them from __CONFIGDIR__). - .TP - .B \-d, \-\-daemon - Run in daemon mode (implies \-\-no\-kbd). -@@ -130,7 +130,7 @@ If logging should be done to LOG_LOCAL\f - LOG_USER, add '.n' to LEVEL, as in 3.7 (n=0..7). - .TP - .BI \-L\ dir ,\ \-\-lib= dir --Search for plugins in directory \fIdir\fR (default is ./PLUGINS/lib). -+Search for plugins in directory \fIdir\fR (default is __PLUGINDIR__). - There can be several \fB\-L\fR options with different \fIdir\fR values. - Each of them will apply to the \fB\-P\fR options following it. - .TP -@@ -205,7 +205,7 @@ For backwards compatibility (same as \-\ - .TP - .BI \-v\ dir ,\ \-\-video= dir - Use \fIdir\fR as video directory. --The default is \fI/video\fR. -+The default is \fI__VIDEODIR__\fR. - .TP - .B \-V, \-\-version - Print version information and exit. -diff -up vdr-1.7.41/vdr.5~ vdr-1.7.41/vdr.5 ---- vdr-1.7.41/vdr.5~ 2013-03-11 15:17:12.000000000 +0200 -+++ vdr-1.7.41/vdr.5 2013-03-16 19:08:18.908726601 +0200 -@@ -711,7 +711,7 @@ The file \fIsetup.conf\fR contains the b - Each line contains one option in the format "Name = Value". - See the MANUAL file for a description of the available options. - .SS THEMES --The files \fIthemes/\-.theme\fR in the config directory contain the -+The files \fI__VARDIR__/themes/\-.theme\fR contain the - color theme definitions for the various skins. In the actual file names \fI\fR - will be replaced by the name if the skin this theme belongs to, and \fI\fR - will be the name of this theme. -diff -up vdr-1.7.41/vdr.c~ vdr-1.7.41/vdr.c ---- vdr-1.7.41/vdr.c~ 2013-03-15 12:44:54.000000000 +0200 -+++ vdr-1.7.41/vdr.c 2013-03-16 19:08:15.861673670 +0200 -@@ -673,7 +673,7 @@ int main(int argc, char *argv[]) - if (!ResourceDirectory) - ResourceDirectory = DEFAULTRESDIR; - cPlugin::SetResourceDirectory(ResourceDirectory); -- cThemes::SetThemesDirectory(AddDirectory(ConfigDirectory, "themes")); -+ cThemes::SetThemesDirectory("__VARDIR__/themes"); - - // Configuration data: - diff --git a/vdr-2.0.4-mainmenuhooks101.patch b/vdr-2.0.4-mainmenuhooks101.patch deleted file mode 100644 index b7b2a5c..0000000 --- a/vdr-2.0.4-mainmenuhooks101.patch +++ /dev/null @@ -1,109 +0,0 @@ -diff -up vdr-2.0.4/config.h~ vdr-2.0.4/config.h ---- vdr-2.0.4/config.h~ 2013-09-07 13:25:10.000000000 +0300 -+++ vdr-2.0.4/config.h 2013-10-23 19:43:24.731445495 +0300 -@@ -47,6 +47,10 @@ - #define TIMERMACRO_TITLE "TITLE" - #define TIMERMACRO_EPISODE "EPISODE" - -+// The MainMenuHook Patch's version number: -+#define MAINMENUHOOKSVERSION "1.0.1" -+#define MAINMENUHOOKSVERSNUM 10001 // Version * 10000 + Major * 100 + Minor -+ - #define MINOSDWIDTH 480 - #define MAXOSDWIDTH 1920 - #define MINOSDHEIGHT 324 -diff -up vdr-2.0.4/menu.c~ vdr-2.0.4/menu.c ---- vdr-2.0.4/menu.c~ 2013-10-16 12:46:24.000000000 +0300 -+++ vdr-2.0.4/menu.c 2013-10-23 19:43:24.275436244 +0300 -@@ -3377,15 +3377,31 @@ cMenuMain::cMenuMain(eOSState State, boo - - // Initial submenus: - -+ cOsdObject *menu = NULL; - switch (State) { -- case osSchedule: AddSubMenu(new cMenuSchedule); break; -- case osChannels: AddSubMenu(new cMenuChannels); break; -- case osTimers: AddSubMenu(new cMenuTimers); break; -- case osRecordings: AddSubMenu(new cMenuRecordings(NULL, 0, OpenSubMenus)); break; -- case osSetup: AddSubMenu(new cMenuSetup); break; -- case osCommands: AddSubMenu(new cMenuCommands(tr("Commands"), &Commands)); break; -+ case osSchedule: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu)) -+ menu = new cMenuSchedule; -+ break; -+ case osChannels: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu)) -+ menu = new cMenuChannels; -+ break; -+ case osTimers: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu)) -+ menu = new cMenuTimers; -+ break; -+ case osRecordings: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu)) -+ menu = new cMenuRecordings(NULL, 0, OpenSubMenus); -+ break; -+ case osSetup: menu = new cMenuSetup; break; -+ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break; - default: break; - } -+ if (menu) -+ if (menu->IsMenu()) -+ AddSubMenu((cOsdMenu *) menu); - } - - cOsdObject *cMenuMain::PluginOsdObject(void) -@@ -3493,13 +3509,34 @@ eOSState cMenuMain::ProcessKey(eKeys Key - eOSState state = cOsdMenu::ProcessKey(Key); - HadSubMenu |= HasSubMenu(); - -+ cOsdObject *menu = NULL; - switch (state) { -- case osSchedule: return AddSubMenu(new cMenuSchedule); -- case osChannels: return AddSubMenu(new cMenuChannels); -- case osTimers: return AddSubMenu(new cMenuTimers); -- case osRecordings: return AddSubMenu(new cMenuRecordings); -- case osSetup: return AddSubMenu(new cMenuSetup); -- case osCommands: return AddSubMenu(new cMenuCommands(tr("Commands"), &Commands)); -+ case osSchedule: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu)) -+ menu = new cMenuSchedule; -+ else -+ state = osContinue; -+ break; -+ case osChannels: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu)) -+ menu = new cMenuChannels; -+ else -+ state = osContinue; -+ break; -+ case osTimers: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu)) -+ menu = new cMenuTimers; -+ else -+ state = osContinue; -+ break; -+ case osRecordings: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu)) -+ menu = new cMenuRecordings; -+ else -+ state = osContinue; -+ break; -+ case osSetup: menu = new cMenuSetup; break; -+ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break; - case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) { - cOsdItem *item = Get(Current()); - if (item) { -@@ -3551,6 +3588,12 @@ eOSState cMenuMain::ProcessKey(eKeys Key - default: break; - } - } -+ if (menu) { -+ if (menu->IsMenu()) -+ return AddSubMenu((cOsdMenu *) menu); -+ pluginOsdObject = menu; -+ return osPlugin; -+ } - if (!HasSubMenu() && Update(HadSubMenu)) - Display(); - if (Key != kNone) { diff --git a/vdr-2.1.5-naludump-0.1.diff b/vdr-2.1.5-naludump-0.1.diff deleted file mode 100644 index 4b338cd..0000000 --- a/vdr-2.1.5-naludump-0.1.diff +++ /dev/null @@ -1,621 +0,0 @@ -diff -Naur vdr-2.1.6/config.c vdr-2.1.6-naludump-0.1/config.c ---- vdr-2.1.6/config.c 2013-08-31 14:41:28.000000000 +0200 -+++ vdr-2.1.6-naludump-0.1/config.c 2014-03-30 17:47:25.000000000 +0200 -@@ -462,6 +462,7 @@ - MaxVideoFileSize = MAXVIDEOFILESIZEDEFAULT; - SplitEditedFiles = 0; - DelTimeshiftRec = 0; -+ DumpNaluFill = 0; - MinEventTimeout = 30; - MinUserInactivity = 300; - NextWakeupTime = 0; -@@ -673,6 +674,7 @@ - else if (!strcasecmp(Name, "MaxVideoFileSize")) MaxVideoFileSize = atoi(Value); - else if (!strcasecmp(Name, "SplitEditedFiles")) SplitEditedFiles = atoi(Value); - else if (!strcasecmp(Name, "DelTimeshiftRec")) DelTimeshiftRec = atoi(Value); -+ else if (!strcasecmp(Name, "DumpNaluFill")) DumpNaluFill = atoi(Value); - else if (!strcasecmp(Name, "MinEventTimeout")) MinEventTimeout = atoi(Value); - else if (!strcasecmp(Name, "MinUserInactivity")) MinUserInactivity = atoi(Value); - else if (!strcasecmp(Name, "NextWakeupTime")) NextWakeupTime = atoi(Value); -@@ -788,6 +790,7 @@ - Store("MaxVideoFileSize", MaxVideoFileSize); - Store("SplitEditedFiles", SplitEditedFiles); - Store("DelTimeshiftRec", DelTimeshiftRec); -+ Store("DumpNaluFill", DumpNaluFill); - Store("MinEventTimeout", MinEventTimeout); - Store("MinUserInactivity", MinUserInactivity); - Store("NextWakeupTime", NextWakeupTime); -diff -Naur vdr-2.1.6/config.h vdr-2.1.6-naludump-0.1/config.h ---- vdr-2.1.6/config.h 2014-02-25 11:00:23.000000000 +0100 -+++ vdr-2.1.6-naludump-0.1/config.h 2014-03-30 17:47:25.000000000 +0200 -@@ -326,6 +326,7 @@ - int MaxVideoFileSize; - int SplitEditedFiles; - int DelTimeshiftRec; -+ int DumpNaluFill; - int MinEventTimeout, MinUserInactivity; - time_t NextWakeupTime; - int MultiSpeedMode; -diff -Naur vdr-2.1.6/menu.c vdr-2.1.6-naludump-0.1/menu.c ---- vdr-2.1.6/menu.c 2014-03-16 11:38:31.000000000 +0100 -+++ vdr-2.1.6-naludump-0.1/menu.c 2014-03-30 17:47:25.000000000 +0200 -@@ -3547,6 +3547,7 @@ - Add(new cMenuEditIntItem( tr("Setup.Recording$Max. video file size (MB)"), &data.MaxVideoFileSize, MINVIDEOFILESIZE, MAXVIDEOFILESIZETS)); - Add(new cMenuEditBoolItem(tr("Setup.Recording$Split edited files"), &data.SplitEditedFiles)); - Add(new cMenuEditStraItem(tr("Setup.Recording$Delete timeshift recording"),&data.DelTimeshiftRec, 3, delTimeshiftRecTexts)); -+ Add(new cMenuEditBoolItem(tr("Setup.Recording$Dump NALU Fill data"), &data.DumpNaluFill)); - } - - // --- cMenuSetupReplay ------------------------------------------------------ -diff -Naur vdr-2.1.6/recorder.c vdr-2.1.6-naludump-0.1/recorder.c ---- vdr-2.1.6/recorder.c 2014-02-21 10:19:52.000000000 +0100 -+++ vdr-2.1.6-naludump-0.1/recorder.c 2014-03-30 17:47:25.000000000 +0200 -@@ -46,6 +46,14 @@ - Type = 0x06; - } - frameDetector = new cFrameDetector(Pid, Type); -+ if ( Type == 0x1B // MPEG4 video -+ && (Setup.DumpNaluFill ? (strstr(FileName, "NALUKEEP") == NULL) : (strstr(FileName, "NALUDUMP") != NULL))) { // MPEG4 -+ isyslog("Starting NALU fill dumper"); -+ naluStreamProcessor = new cNaluStreamProcessor(); -+ naluStreamProcessor->SetPid(Pid); -+ } -+ else -+ naluStreamProcessor = NULL; - index = NULL; - fileSize = 0; - lastDiskSpaceCheck = time(NULL); -@@ -67,6 +75,12 @@ - cRecorder::~cRecorder() - { - Detach(); -+ if (naluStreamProcessor) { -+ long long int TotalPackets = naluStreamProcessor->GetTotalPackets(); -+ long long int DroppedPackets = naluStreamProcessor->GetDroppedPackets(); -+ isyslog("NALU fill dumper: %lld of %lld packets dropped, %lli%%", DroppedPackets, TotalPackets, TotalPackets ? DroppedPackets*100/TotalPackets : 0); -+ delete naluStreamProcessor; -+ } - delete index; - delete fileName; - delete frameDetector; -@@ -157,11 +171,32 @@ - } - t.Set(MAXBROKENTIMEOUT); - } -- if (recordFile->Write(b, Count) < 0) { -- LOG_ERROR_STR(fileName->Name()); -- break; -+ if (naluStreamProcessor) { -+ naluStreamProcessor->PutBuffer(b, Count); -+ bool Fail = false; -+ while (true) { -+ int OutLength = 0; -+ uchar *OutData = naluStreamProcessor->GetBuffer(OutLength); -+ if (!OutData || OutLength <= 0) -+ break; -+ if (recordFile->Write(OutData, OutLength) < 0) { -+ LOG_ERROR_STR(fileName->Name()); -+ Fail = true; -+ break; -+ } -+ fileSize += OutLength; -+ } -+ if (Fail) -+ break; -+ } -+ else { -+ if (recordFile->Write(b, Count) < 0) { -+ LOG_ERROR_STR(fileName->Name()); -+ break; -+ } -+ fileSize += Count; - } -- fileSize += Count; -+ - } - } - ringBuffer->Del(Count); -diff -Naur vdr-2.1.6/recorder.h vdr-2.1.6-naludump-0.1/recorder.h ---- vdr-2.1.6/recorder.h 2010-12-27 12:17:04.000000000 +0100 -+++ vdr-2.1.6-naludump-0.1/recorder.h 2014-03-30 17:47:25.000000000 +0200 -@@ -21,6 +21,7 @@ - cRingBufferLinear *ringBuffer; - cFrameDetector *frameDetector; - cPatPmtGenerator patPmtGenerator; -+ cNaluStreamProcessor *naluStreamProcessor; - cFileName *fileName; - cIndexFile *index; - cUnbufferedFile *recordFile; -diff -Naur vdr-2.1.6/remux.c vdr-2.1.6-naludump-0.1/remux.c ---- vdr-2.1.6/remux.c 2014-03-08 16:05:35.000000000 +0100 -+++ vdr-2.1.6-naludump-0.1/remux.c 2014-03-30 17:47:25.000000000 +0200 -@@ -343,6 +343,42 @@ - dsyslog("WARNING: required %d video TS packets to determine frame type", numPacketsPid); - } - -+void TsExtendAdaptionField(unsigned char *Packet, int ToLength) -+{ -+ // Hint: ExtenAdaptionField(p, TsPayloadOffset(p) - 4) is a null operation -+ -+ int Offset = TsPayloadOffset(Packet); // First byte after existing adaption field -+ -+ if (ToLength <= 0) -+ { -+ // Remove adaption field -+ Packet[3] = Packet[3] & ~TS_ADAPT_FIELD_EXISTS; -+ return; -+ } -+ -+ // Set adaption field present -+ Packet[3] = Packet[3] | TS_ADAPT_FIELD_EXISTS; -+ -+ // Set new length of adaption field: -+ Packet[4] = ToLength <= TS_SIZE-4 ? ToLength-1 : TS_SIZE-4-1; -+ -+ if (Packet[4] == TS_SIZE-4-1) -+ { -+ // No more payload, remove payload flag -+ Packet[3] = Packet[3] & ~TS_PAYLOAD_EXISTS; -+ } -+ -+ int NewPayload = TsPayloadOffset(Packet); // First byte after new adaption field -+ -+ // Fill new adaption field -+ if (Offset == 4 && Offset < NewPayload) -+ Offset++; // skip adaptation_field_length -+ if (Offset == 5 && Offset < NewPayload) -+ Packet[Offset++] = 0; // various flags set to 0 -+ while (Offset < NewPayload) -+ Packet[Offset++] = 0xff; // stuffing byte -+} -+ - // --- cPatPmtGenerator ------------------------------------------------------ - - cPatPmtGenerator::cPatPmtGenerator(const cChannel *Channel) -@@ -1547,3 +1583,344 @@ - } - return Processed; - } -+ -+// --- cNaluDumper --------------------------------------------------------- -+ -+cNaluDumper::cNaluDumper() -+{ -+ LastContinuityOutput = -1; -+ reset(); -+} -+ -+void cNaluDumper::reset() -+{ -+ LastContinuityInput = -1; -+ ContinuityOffset = 0; -+ PesId = -1; -+ PesOffset = 0; -+ NaluFillState = NALU_NONE; -+ NaluOffset = 0; -+ History = 0xffffffff; -+ DropAllPayload = false; -+} -+ -+void cNaluDumper::ProcessPayload(unsigned char *Payload, int size, bool PayloadStart, sPayloadInfo &Info) -+{ -+ Info.DropPayloadStartBytes = 0; -+ Info.DropPayloadEndBytes = 0; -+ int LastKeepByte = -1; -+ -+ if (PayloadStart) -+ { -+ History = 0xffffffff; -+ PesId = -1; -+ NaluFillState = NALU_NONE; -+ } -+ -+ for (int i=0; i= 0x00000180 && History <= 0x000001FF) -+ { -+ // Start of PES packet -+ PesId = History & 0xff; -+ PesOffset = 0; -+ NaluFillState = NALU_NONE; -+ } -+ else if (PesId >= 0xe0 && PesId <= 0xef // video stream -+ && History >= 0x00000100 && History <= 0x0000017F) // NALU start code -+ { -+ int NaluId = History & 0xff; -+ NaluOffset = 0; -+ NaluFillState = ((NaluId & 0x1f) == 0x0c) ? NALU_FILL : NALU_NONE; -+ } -+ -+ if (PesId >= 0xe0 && PesId <= 0xef // video stream -+ && PesOffset >= 1 && PesOffset <= 2) -+ { -+ Payload[i] = 0; // Zero out PES length field -+ } -+ -+ if (NaluFillState == NALU_FILL && NaluOffset > 0) // Within NALU fill data -+ { -+ // We expect a series of 0xff bytes terminated by a single 0x80 byte. -+ -+ if (Payload[i] == 0xFF) -+ { -+ DropByte = true; -+ } -+ else if (Payload[i] == 0x80) -+ { -+ NaluFillState = NALU_TERM; // Last byte of NALU fill, next byte sets NaluFillEnd=true -+ DropByte = true; -+ } -+ else // Invalid NALU fill -+ { -+ dsyslog("cNaluDumper: Unexpected NALU fill data: %02x", Payload[i]); -+ NaluFillState = NALU_END; -+ if (LastKeepByte == -1) -+ { -+ // Nalu fill from beginning of packet until last byte -+ // packet start needs to be dropped -+ Info.DropPayloadStartBytes = i; -+ } -+ } -+ } -+ else if (NaluFillState == NALU_TERM) // Within NALU fill data -+ { -+ // We are after the terminating 0x80 byte -+ NaluFillState = NALU_END; -+ if (LastKeepByte == -1) -+ { -+ // Nalu fill from beginning of packet until last byte -+ // packet start needs to be dropped -+ Info.DropPayloadStartBytes = i; -+ } -+ } -+ -+ if (!DropByte) -+ LastKeepByte = i; // Last useful byte -+ } -+ -+ Info.DropAllPayloadBytes = (LastKeepByte == -1); -+ Info.DropPayloadEndBytes = size-1-LastKeepByte; -+} -+ -+bool cNaluDumper::ProcessTSPacket(unsigned char *Packet) -+{ -+ bool HasAdaption = TsHasAdaptationField(Packet); -+ bool HasPayload = TsHasPayload(Packet); -+ -+ // Check continuity: -+ int ContinuityInput = TsContinuityCounter(Packet); -+ if (LastContinuityInput >= 0) -+ { -+ int NewContinuityInput = HasPayload ? (LastContinuityInput + 1) & TS_CONT_CNT_MASK : LastContinuityInput; -+ int Offset = (NewContinuityInput - ContinuityInput) & TS_CONT_CNT_MASK; -+ if (Offset > 0) -+ dsyslog("cNaluDumper: TS continuity offset %i", Offset); -+ if (Offset > ContinuityOffset) -+ ContinuityOffset = Offset; // max if packets get dropped, otherwise always the current one. -+ } -+ LastContinuityInput = ContinuityInput; -+ -+ if (HasPayload) { -+ sPayloadInfo Info; -+ int Offset = TsPayloadOffset(Packet); -+ ProcessPayload(Packet + Offset, TS_SIZE - Offset, TsPayloadStart(Packet), Info); -+ -+ if (DropAllPayload && !Info.DropAllPayloadBytes) -+ { -+ // Return from drop packet mode to normal mode -+ DropAllPayload = false; -+ -+ // Does the packet start with some remaining NALU fill data? -+ if (Info.DropPayloadStartBytes > 0) -+ { -+ // Add these bytes as stuffing to the adaption field. -+ -+ // Sample payload layout: -+ // FF FF FF FF FF 80 00 00 01 xx xx xx xx -+ // ^DropPayloadStartBytes -+ -+ TsExtendAdaptionField(Packet, Offset - 4 + Info.DropPayloadStartBytes); -+ } -+ } -+ -+ bool DropThisPayload = DropAllPayload; -+ -+ if (!DropAllPayload && Info.DropPayloadEndBytes > 0) // Payload ends with 0xff NALU Fill -+ { -+ // Last packet of useful data -+ // Do early termination of NALU fill data -+ Packet[TS_SIZE-1] = 0x80; -+ DropAllPayload = true; -+ // Drop all packets AFTER this one -+ -+ // Since we already wrote the 0x80, we have to make sure that -+ // as soon as we stop dropping packets, any beginning NALU fill of next -+ // packet gets dumped. (see DropPayloadStartBytes above) -+ } -+ -+ if (DropThisPayload && HasAdaption) -+ { -+ // Drop payload data, but keep adaption field data -+ TsExtendAdaptionField(Packet, TS_SIZE-4); -+ DropThisPayload = false; -+ } -+ -+ if (DropThisPayload) -+ { -+ return true; // Drop packet -+ } -+ } -+ -+ // Fix Continuity Counter and reproduce incoming offsets: -+ int NewContinuityOutput = TsHasPayload(Packet) ? (LastContinuityOutput + 1) & TS_CONT_CNT_MASK : LastContinuityOutput; -+ NewContinuityOutput = (NewContinuityOutput + ContinuityOffset) & TS_CONT_CNT_MASK; -+ TsSetContinuityCounter(Packet, NewContinuityOutput); -+ LastContinuityOutput = NewContinuityOutput; -+ ContinuityOffset = 0; -+ -+ return false; // Keep packet -+} -+ -+// --- cNaluStreamProcessor --------------------------------------------------------- -+ -+cNaluStreamProcessor::cNaluStreamProcessor() -+{ -+ pPatPmtParser = NULL; -+ vpid = -1; -+ data = NULL; -+ length = 0; -+ tempLength = 0; -+ tempLengthAtEnd = false; -+ TotalPackets = 0; -+ DroppedPackets = 0; -+} -+ -+void cNaluStreamProcessor::PutBuffer(uchar *Data, int Length) -+{ -+ if (length > 0) -+ esyslog("cNaluStreamProcessor::PutBuffer: New data before old data was processed!"); -+ -+ data = Data; -+ length = Length; -+} -+ -+uchar* cNaluStreamProcessor::GetBuffer(int &OutLength) -+{ -+ if (length <= 0) -+ { -+ // Need more data - quick exit -+ OutLength = 0; -+ return NULL; -+ } -+ if (tempLength > 0) // Data in temp buffer? -+ { -+ if (tempLengthAtEnd) // Data is at end, copy to beginning -+ { -+ // Overlapping src and dst! -+ for (int i=0; i 0) -+ { -+ int Size = min(TS_SIZE-tempLength, length); -+ memcpy(tempBuffer+tempLength, data, Size); -+ data += Size; -+ length -= Size; -+ tempLength += Size; -+ } -+ if (tempLength < TS_SIZE) -+ { -+ // All incoming data buffered, but need more data -+ tempLengthAtEnd = false; -+ OutLength = 0; -+ return NULL; -+ } -+ // Now: TempLength==TS_SIZE -+ if (tempBuffer[0] != TS_SYNC_BYTE) -+ { -+ // Need to sync on TS within temp buffer -+ int Skipped = 1; -+ while (Skipped < TS_SIZE && (tempBuffer[Skipped] != TS_SYNC_BYTE || (Skipped < length && data[Skipped] != TS_SYNC_BYTE))) -+ Skipped++; -+ esyslog("ERROR: skipped %d bytes to sync on start of TS packet", Skipped); -+ // Pass through skipped bytes -+ tempLengthAtEnd = true; -+ tempLength = TS_SIZE - Skipped; // may be 0, thats ok -+ OutLength = Skipped; -+ return tempBuffer; -+ } -+ // Now: TempBuffer is a TS packet -+ int Pid = TsPid(tempBuffer); -+ if (pPatPmtParser) -+ { -+ if (Pid == 0) -+ pPatPmtParser->ParsePat(tempBuffer, TS_SIZE); -+ else if (pPatPmtParser->IsPmtPid(Pid)) -+ pPatPmtParser->ParsePmt(tempBuffer, TS_SIZE); -+ } -+ -+ TotalPackets++; -+ bool Drop = false; -+ if (Pid == vpid || (pPatPmtParser && Pid == pPatPmtParser->Vpid() && pPatPmtParser->Vtype() == 0x1B)) -+ Drop = NaluDumper.ProcessTSPacket(tempBuffer); -+ if (!Drop) -+ { -+ // Keep this packet, then continue with new data -+ tempLength = 0; -+ OutLength = TS_SIZE; -+ return tempBuffer; -+ } -+ // Drop TempBuffer -+ DroppedPackets++; -+ tempLength = 0; -+ } -+ // Now: TempLength==0, just process data/length -+ -+ // Pointer to processed data / length: -+ uchar *Out = data; -+ uchar *OutEnd = Out; -+ -+ while (length >= TS_SIZE) -+ { -+ if (data[0] != TS_SYNC_BYTE) { -+ int Skipped = 1; -+ while (Skipped < length && (data[Skipped] != TS_SYNC_BYTE || (length - Skipped > TS_SIZE && data[Skipped + TS_SIZE] != TS_SYNC_BYTE))) -+ Skipped++; -+ esyslog("ERROR: skipped %d bytes to sync on start of TS packet", Skipped); -+ -+ // Pass through skipped bytes -+ if (OutEnd != data) -+ memcpy(OutEnd, data, Skipped); -+ OutEnd += Skipped; -+ continue; -+ } -+ // Now: Data starts with complete TS packet -+ -+ int Pid = TsPid(data); -+ if (pPatPmtParser) -+ { -+ if (Pid == 0) -+ pPatPmtParser->ParsePat(data, TS_SIZE); -+ else if (pPatPmtParser->IsPmtPid(Pid)) -+ pPatPmtParser->ParsePmt(data, TS_SIZE); -+ } -+ -+ TotalPackets++; -+ bool Drop = false; -+ if (Pid == vpid || (pPatPmtParser && Pid == pPatPmtParser->Vpid() && pPatPmtParser->Vtype() == 0x1B)) -+ Drop = NaluDumper.ProcessTSPacket(data); -+ if (!Drop) -+ { -+ if (OutEnd != data) -+ memcpy(OutEnd, data, TS_SIZE); -+ OutEnd += TS_SIZE; -+ } -+ else -+ { -+ DroppedPackets++; -+ } -+ data += TS_SIZE; -+ length -= TS_SIZE; -+ } -+ // Now: Less than a packet remains. -+ if (length > 0) -+ { -+ // copy remains into temp buffer -+ memcpy(tempBuffer, data, length); -+ tempLength = length; -+ tempLengthAtEnd = false; -+ length = 0; -+ } -+ OutLength = (OutEnd - Out); -+ return OutLength > 0 ? Out : NULL; -+} -diff -Naur vdr-2.1.6/remux.h vdr-2.1.6-naludump-0.1/remux.h ---- vdr-2.1.6/remux.h 2014-02-08 13:41:50.000000000 +0100 -+++ vdr-2.1.6-naludump-0.1/remux.h 2014-03-30 17:47:25.000000000 +0200 -@@ -62,6 +62,11 @@ - return p[3] & TS_PAYLOAD_EXISTS; - } - -+inline bool TsSetPayload(const uchar *p) -+{ -+ return p[3] & TS_PAYLOAD_EXISTS; -+} -+ - inline bool TsHasAdaptationField(const uchar *p) - { - return p[3] & TS_ADAPT_FIELD_EXISTS; -@@ -143,6 +148,7 @@ - int64_t TsGetDts(const uchar *p, int l); - void TsSetPts(uchar *p, int l, int64_t Pts); - void TsSetDts(uchar *p, int l, int64_t Dts); -+void TsExtendAdaptionField(unsigned char *Packet, int ToLength); - - // Some PES handling tools: - // The following functions that take a pointer to PES data all assume that -@@ -518,4 +524,78 @@ - ///< available. - }; - -+ -+#define PATCH_NALUDUMP 100 -+ -+class cNaluDumper { -+ unsigned int History; -+ -+ int LastContinuityInput; -+ int LastContinuityOutput; -+ int ContinuityOffset; -+ -+ bool DropAllPayload; -+ -+ int PesId; -+ int PesOffset; -+ -+ int NaluOffset; -+ -+ enum eNaluFillState { -+ NALU_NONE=0, // currently not NALU fill stream -+ NALU_FILL, // Within NALU fill stream, 0xff bytes and NALU start code in byte 0 -+ NALU_TERM, // Within NALU fill stream, read 0x80 terminating byte -+ NALU_END // Beyond end of NALU fill stream, expecting 0x00 0x00 0x01 now -+ }; -+ -+ eNaluFillState NaluFillState; -+ -+ struct sPayloadInfo { -+ int DropPayloadStartBytes; -+ int DropPayloadEndBytes; -+ bool DropAllPayloadBytes; -+ }; -+ -+public: -+ cNaluDumper(); -+ -+ void reset(); -+ -+ // Single packet interface: -+ bool ProcessTSPacket(unsigned char *Packet); -+ -+private: -+ void ProcessPayload(unsigned char *Payload, int size, bool PayloadStart, sPayloadInfo &Info); -+}; -+ -+class cNaluStreamProcessor { -+ //Buffer stream interface: -+ int vpid; -+ uchar *data; -+ int length; -+ uchar tempBuffer[TS_SIZE]; -+ int tempLength; -+ bool tempLengthAtEnd; -+ cPatPmtParser *pPatPmtParser; -+ cNaluDumper NaluDumper; -+ -+ long long int TotalPackets; -+ long long int DroppedPackets; -+public: -+ cNaluStreamProcessor(); -+ -+ void SetPid(int VPid) { vpid = VPid; } -+ void SetPatPmtParser(cPatPmtParser *_pPatPmtParser) { pPatPmtParser = _pPatPmtParser; } -+ // Set either a PID or set a pointer to an PatPmtParser that will detect _one_ PID -+ -+ void PutBuffer(uchar *Data, int Length); -+ // Add new data to be processed. Data must be valid until Get() returns NULL. -+ uchar* GetBuffer(int &OutLength); -+ // Returns filtered data, or NULL/0 to indicate that all data from Put() was processed -+ // or buffered. -+ -+ long long int GetTotalPackets() { return TotalPackets; } -+ long long int GetDroppedPackets() { return DroppedPackets; } -+}; -+ - #endif // __REMUX_H diff --git a/vdr-2.2.0-ttxtsubs.patch b/vdr-2.2.0-ttxtsubs.patch deleted file mode 100644 index 929210f..0000000 --- a/vdr-2.2.0-ttxtsubs.patch +++ /dev/null @@ -1,1016 +0,0 @@ -diff --git a/MANUAL b/MANUAL -index 3c4003e..e8de3ad 100644 ---- a/MANUAL -+++ b/MANUAL -@@ -810,6 +810,9 @@ Version 2.2 - background transparency. By default the values as broadcast - are used. - -+ Enable teletext support = yes -+ If set to 'yes', enables teletext subtitles. -+ - LNB: - - Use DiSEqC = no Generally turns DiSEqC support on or off. -diff --git a/Makefile b/Makefile -index 9722036..92db319 100644 ---- a/Makefile -+++ b/Makefile -@@ -74,6 +74,8 @@ OBJS = args.o audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdev - skinclassic.o skinlcars.o skins.o skinsttng.o sourceparams.o sources.o spu.o status.o svdrp.o themes.o thread.o\ - timers.o tools.o transfer.o vdr.o videodir.o - -+OBJS += vdrttxtsubshooks.o -+ - DEFINES += $(CDEFINES) - INCLUDES += $(CINCLUDES) - -diff --git a/channels.c b/channels.c -index 564088f..d0fc3d8 100644 ---- a/channels.c -+++ b/channels.c -@@ -421,6 +421,26 @@ void cChannel::SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *Compos - } - } - -+void cChannel::SetTeletextSubtitlePages(tTeletextSubtitlePage pages[], int numberOfPages) -+{ -+ int mod = CHANNELMOD_NONE; -+ if (totalTtxtSubtitlePages != (fixedTtxtSubtitlePages + numberOfPages)) -+ mod |= CHANNELMOD_PIDS; -+ totalTtxtSubtitlePages = fixedTtxtSubtitlePages; -+ for (int i = 0; (i < numberOfPages) && (totalTtxtSubtitlePages < MAXTXTPAGES); i++) { -+ if (teletextSubtitlePages[totalTtxtSubtitlePages].ttxtMagazine != pages[i].ttxtMagazine || -+ teletextSubtitlePages[totalTtxtSubtitlePages].ttxtPage != pages[i].ttxtPage || -+ teletextSubtitlePages[totalTtxtSubtitlePages].ttxtType != pages[i].ttxtType || -+ strcmp(teletextSubtitlePages[totalTtxtSubtitlePages].ttxtLanguage, pages[i].ttxtLanguage)) { -+ mod |= CHANNELMOD_PIDS; -+ teletextSubtitlePages[totalTtxtSubtitlePages] = pages[i]; -+ } -+ totalTtxtSubtitlePages++; -+ } -+ modification |= mod; -+ Channels.SetModified(); -+} -+ - void cChannel::SetSeen(void) - { - seen = time(NULL); -@@ -556,10 +576,17 @@ cString cChannel::ToText(const cChannel *Channel) - q += IntArrayToString(q, Channel->dpids, 10, Channel->dlangs, Channel->dtypes); - } - *q = 0; -- const int TBufferSize = MAXSPIDS * (5 + 1 + MAXLANGCODE2) + 10; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod', +10: paranoia and tpid -+ const int TBufferSize = (MAXTXTPAGES * MAXSPIDS) * (5 + 1 + MAXLANGCODE2) + 10; // 5 digits plus delimiting ',' or ';' plus optional '=cod+cod', +10: paranoia and tpid - char tpidbuf[TBufferSize]; - q = tpidbuf; - q += snprintf(q, sizeof(tpidbuf), "%d", Channel->tpid); -+ if (Channel->fixedTtxtSubtitlePages > 0) { -+ *q++ = '+'; -+ for (int i = 0; i < Channel->fixedTtxtSubtitlePages; ++i) { -+ tTeletextSubtitlePage page = Channel->teletextSubtitlePages[i]; -+ q += snprintf(q, sizeof(tpidbuf) - (q - tpidbuf), "%d=%s", page.PageNumber(), page.ttxtLanguage); -+ } -+ } - if (Channel->spids[0]) { - *q++ = ';'; - q += IntArrayToString(q, Channel->spids, 10, Channel->slangs); -@@ -730,6 +757,32 @@ bool cChannel::Parse(const char *s) - } - spids[NumSpids] = 0; - } -+ fixedTtxtSubtitlePages = 0; -+ if ((p = strchr(tpidbuf, '+')) != NULL) { -+ *p++ = 0; -+ char *q; -+ char *strtok_next; -+ while ((q = strtok_r(p, ",", &strtok_next)) != NULL) { -+ if (fixedTtxtSubtitlePages < MAXTXTPAGES) { -+ int page; -+ char *l = strchr(q, '='); -+ if (l) -+ *l++ = 0; -+ if (sscanf(q, "%d", &page) == 1) { -+ teletextSubtitlePages[fixedTtxtSubtitlePages] = tTeletextSubtitlePage(page); -+ if (l) -+ strn0cpy(teletextSubtitlePages[fixedTtxtSubtitlePages].ttxtLanguage, l, MAXLANGCODE2); -+ fixedTtxtSubtitlePages++; -+ } -+ else -+ esyslog("ERROR: invalid Teletext page!"); // no need to set ok to 'false' -+ } -+ else -+ esyslog("ERROR: too many Teletext pages!"); // no need to set ok to 'false' -+ p = NULL; -+ } -+ totalTtxtSubtitlePages = fixedTtxtSubtitlePages; -+ } - if (sscanf(tpidbuf, "%d", &tpid) != 1) - return false; - if (caidbuf) { -diff --git a/channels.h b/channels.h -index 3323882..c62fdec 100644 ---- a/channels.h -+++ b/channels.h -@@ -36,6 +36,7 @@ - #define MAXDPIDS 16 // dolby (AC3 + DTS) - #define MAXSPIDS 32 // subtitles - #define MAXCAIDS 12 // conditional access -+#define MAXTXTPAGES 8 // teletext pages - - #define MAXLANGCODE1 4 // a 3 letter language code, zero terminated - #define MAXLANGCODE2 8 // up to two 3 letter language codes, separated by '+' and zero terminated -@@ -72,6 +73,16 @@ public: - static const tChannelID InvalidID; - }; - -+struct tTeletextSubtitlePage { -+ tTeletextSubtitlePage(void) { ttxtPage = ttxtMagazine = 0; ttxtType = 0x02; strcpy(ttxtLanguage, "und"); } -+ tTeletextSubtitlePage(int page) { ttxtMagazine = (page / 100) & 0x7; ttxtPage = (((page % 100) / 10) << 4) + (page % 10); ttxtType = 0x02; strcpy(ttxtLanguage, "und"); } -+ char ttxtLanguage[MAXLANGCODE1]; -+ uchar ttxtPage; -+ uchar ttxtMagazine; -+ uchar ttxtType; -+ int PageNumber(void) const { return BCDCHARTOINT(ttxtMagazine) * 100 + BCDCHARTOINT(ttxtPage); } -+ }; -+ - class cChannel; - - class cLinkChannel : public cListObject { -@@ -116,6 +127,9 @@ private: - uint16_t compositionPageIds[MAXSPIDS]; - uint16_t ancillaryPageIds[MAXSPIDS]; - int tpid; -+ int fixedTtxtSubtitlePages; -+ int totalTtxtSubtitlePages; -+ tTeletextSubtitlePage teletextSubtitlePages[MAXTXTPAGES]; - int caids[MAXCAIDS + 1]; // list is zero-terminated - int nid; - int tid; -@@ -169,6 +183,8 @@ public: - uint16_t CompositionPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? compositionPageIds[i] : uint16_t(0); } - uint16_t AncillaryPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? ancillaryPageIds[i] : uint16_t(0); } - int Tpid(void) const { return tpid; } -+ const tTeletextSubtitlePage *TeletextSubtitlePages() const { return teletextSubtitlePages; } -+ int TotalTeletextSubtitlePages() const { return totalTtxtSubtitlePages; } - const int *Caids(void) const { return caids; } - int Ca(int Index = 0) const { return Index < MAXCAIDS ? caids[Index] : 0; } - int Nid(void) const { return nid; } -@@ -198,6 +214,7 @@ public: - void SetName(const char *Name, const char *ShortName, const char *Provider); - void SetPortalName(const char *PortalName); - void SetPids(int Vpid, int Ppid, int Vtype, int *Apids, int *Atypes, char ALangs[][MAXLANGCODE2], int *Dpids, int *Dtypes, char DLangs[][MAXLANGCODE2], int *Spids, char SLangs[][MAXLANGCODE2], int Tpid); -+ void SetTeletextSubtitlePages(tTeletextSubtitlePage pages[], int numberOfPages); - void SetCaIds(const int *CaIds); // list must be zero-terminated - void SetCaDescriptors(int Level); - void SetLinkChannels(cLinkChannels *LinkChannels); -diff --git a/ci.c b/ci.c -index ffc7ff7..b6c5753 100644 ---- a/ci.c -+++ b/ci.c -@@ -2155,6 +2155,8 @@ void cCamSlot::AddChannel(const cChannel *Channel) - AddPid(Channel->Sid(), *Dpid, STREAM_TYPE_PRIVATE); - for (const int *Spid = Channel->Spids(); *Spid; Spid++) - AddPid(Channel->Sid(), *Spid, STREAM_TYPE_PRIVATE); -+ if (Channel->Tpid() && Setup.SupportTeletext) -+ AddPid(Channel->Sid(), Channel->Tpid(), STREAM_TYPE_PRIVATE); - } - } - -@@ -2178,6 +2180,9 @@ bool cCamSlot::CanDecrypt(const cChannel *Channel) - CaPmt.AddPid(*Dpid, STREAM_TYPE_PRIVATE); - for (const int *Spid = Channel->Spids(); *Spid; Spid++) - CaPmt.AddPid(*Spid, STREAM_TYPE_PRIVATE); -+ if (Channel->Tpid() && Setup.SupportTeletext) { -+ CaPmt.AddPid(Channel->Tpid(), STREAM_TYPE_PRIVATE); -+ } - cas->SendPMT(&CaPmt); - cTimeMs Timeout(QUERY_REPLY_TIMEOUT); - do { -diff --git a/config.c b/config.c -index 9c6b71e..83e2e6f 100644 ---- a/config.c -+++ b/config.c -@@ -403,6 +403,7 @@ cSetup::cSetup(void) - MarginStop = 10; - AudioLanguages[0] = -1; - DisplaySubtitles = 0; -+ SupportTeletext = 1; - SubtitleLanguages[0] = -1; - SubtitleOffset = 0; - SubtitleFgTransparency = 0; -@@ -625,6 +626,7 @@ bool cSetup::Parse(const char *Name, const char *Value) - else if (!strcasecmp(Name, "MarginStop")) MarginStop = atoi(Value); - else if (!strcasecmp(Name, "AudioLanguages")) return ParseLanguages(Value, AudioLanguages); - else if (!strcasecmp(Name, "DisplaySubtitles")) DisplaySubtitles = atoi(Value); -+ else if (!strcasecmp(Name, "SupportTeletext")) SupportTeletext = atoi(Value); - else if (!strcasecmp(Name, "SubtitleLanguages")) return ParseLanguages(Value, SubtitleLanguages); - else if (!strcasecmp(Name, "SubtitleOffset")) SubtitleOffset = atoi(Value); - else if (!strcasecmp(Name, "SubtitleFgTransparency")) SubtitleFgTransparency = atoi(Value); -@@ -751,6 +753,7 @@ bool cSetup::Save(void) - Store("MarginStop", MarginStop); - StoreLanguages("AudioLanguages", AudioLanguages); - Store("DisplaySubtitles", DisplaySubtitles); -+ Store("SupportTeletext", SupportTeletext); - StoreLanguages("SubtitleLanguages", SubtitleLanguages); - Store("SubtitleOffset", SubtitleOffset); - Store("SubtitleFgTransparency", SubtitleFgTransparency); -diff --git a/config.h b/config.h -index d1bae04..db1cbe1 100644 ---- a/config.h -+++ b/config.h -@@ -280,6 +280,7 @@ public: - int MarginStart, MarginStop; - int AudioLanguages[I18N_MAX_LANGUAGES + 1]; - int DisplaySubtitles; -+ int SupportTeletext; - int SubtitleLanguages[I18N_MAX_LANGUAGES + 1]; - int SubtitleOffset; - int SubtitleFgTransparency, SubtitleBgTransparency; -diff --git a/device.c b/device.c -index 14ab07d..d4a6f5d 100644 ---- a/device.c -+++ b/device.c -@@ -19,6 +19,7 @@ - #include "receiver.h" - #include "status.h" - #include "transfer.h" -+#include "vdrttxtsubshooks.h" - - // --- cLiveSubtitle --------------------------------------------------------- - -@@ -1321,6 +1322,13 @@ int cDevice::PlayPesPacket(const uchar *Data, int Length, bool VideoOnly) - } - break; - case 0xBD: { // private stream 1 -+ // EBU Teletext data, ETSI EN 300 472 -+ // if PES data header length = 24 and data_identifier = 0x10..0x1F (EBU Data) -+ if (Data[8] == 0x24 && Data[45] >= 0x10 && Data[45] < 0x20) { -+ cVDRTtxtsubsHookListener::Hook()->PlayerTeletextData((uint8_t*)Data, Length); -+ break; -+ } -+ - int PayloadOffset = Data[8] + 9; - - // Compatibility mode for old subtitles plugin: -@@ -1480,6 +1488,7 @@ int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly) - tsToPesVideo.Reset(); - tsToPesAudio.Reset(); - tsToPesSubtitle.Reset(); -+ tsToPesTeletext.Reset(); - } - else if (Length < TS_SIZE) { - esyslog("ERROR: skipped %d bytes of TS fragment", Length); -@@ -1524,6 +1533,17 @@ int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly) - if (!VideoOnly || HasIBPTrickSpeed()) - PlayTsSubtitle(Data, TS_SIZE); - } -+ else if (Pid == patPmtParser.Tpid()) { -+ if (!VideoOnly || HasIBPTrickSpeed()) { -+ int l; -+ tsToPesTeletext.PutTs(Data, Length); -+ if (const uchar *p = tsToPesTeletext.GetPes(l)) { -+ if ((l > 45) && (p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xbd) && (p[8] == 0x24) && (p[45] >= 0x10) && (p[45] < 0x20)) -+ cVDRTtxtsubsHookListener::Hook()->PlayerTeletextData((uchar *)p, l, false, patPmtParser.TeletextSubtitlePages(), patPmtParser.TotalTeletextSubtitlePages()); -+ tsToPesTeletext.Reset(); -+ } -+ } -+ } - } - } - else if (Pid == patPmtParser.Ppid()) { -diff --git a/device.h b/device.h -index b06d977..25a7bbe 100644 ---- a/device.h -+++ b/device.h -@@ -602,6 +602,7 @@ private: - cTsToPes tsToPesVideo; - cTsToPes tsToPesAudio; - cTsToPes tsToPesSubtitle; -+ cTsToPes tsToPesTeletext; - bool isPlayingVideo; - protected: - const cPatPmtParser *PatPmtParser(void) const { return &patPmtParser; } -diff --git a/menu.c b/menu.c -index ae61c64..a0dba1b 100644 ---- a/menu.c -+++ b/menu.c -@@ -3326,6 +3326,7 @@ void cMenuSetupDVB::Setup(void) - Add(new cMenuEditIntItem( tr("Setup.DVB$Subtitle foreground transparency"), &data.SubtitleFgTransparency, 0, 9)); - Add(new cMenuEditIntItem( tr("Setup.DVB$Subtitle background transparency"), &data.SubtitleBgTransparency, 0, 10)); - } -+ Add(new cMenuEditBoolItem(tr("Setup.DVB$Enable teletext support"), &data.SupportTeletext)); - - SetCurrent(Get(current)); - Display(); -diff --git a/pat.c b/pat.c -index 98d306e..4ca0d5a 100644 ---- a/pat.c -+++ b/pat.c -@@ -12,6 +12,7 @@ - #include "channels.h" - #include "libsi/section.h" - #include "libsi/descriptor.h" -+#include "vdrttxtsubshooks.h" - - #define PMT_SCAN_TIMEOUT 1000 // ms - -@@ -426,6 +427,8 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length - char DLangs[MAXDPIDS][MAXLANGCODE2] = { "" }; - char SLangs[MAXSPIDS][MAXLANGCODE2] = { "" }; - int Tpid = 0; -+ tTeletextSubtitlePage TeletextSubtitlePages[MAXTXTPAGES]; -+ int NumTPages = 0; - int NumApids = 0; - int NumDpids = 0; - int NumSpids = 0; -@@ -517,8 +520,21 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length - NumSpids++; - } - break; -- case SI::TeletextDescriptorTag: -+ case SI::TeletextDescriptorTag: { - Tpid = esPid; -+ SI::TeletextDescriptor *sd = (SI::TeletextDescriptor *)d; -+ SI::TeletextDescriptor::Teletext ttxt; -+ for (SI::Loop::Iterator it; sd->teletextLoop.getNext(ttxt, it); ) { -+ bool isSubtitlePage = (ttxt.getTeletextType() == 0x02) || (ttxt.getTeletextType() == 0x05); -+ if ((NumTPages < MAXTXTPAGES) && ttxt.languageCode[0] && isSubtitlePage) { -+ strn0cpy(TeletextSubtitlePages[NumTPages].ttxtLanguage, I18nNormalizeLanguageCode(ttxt.languageCode), MAXLANGCODE1); -+ TeletextSubtitlePages[NumTPages].ttxtPage = ttxt.getTeletextPageNumber(); -+ TeletextSubtitlePages[NumTPages].ttxtMagazine = ttxt.getTeletextMagazineNumber(); -+ TeletextSubtitlePages[NumTPages].ttxtType = ttxt.getTeletextType(); -+ NumTPages++; -+ } -+ } -+ } - break; - case SI::ISO639LanguageDescriptorTag: { - SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d; -@@ -630,6 +646,12 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length - } - if (Setup.UpdateChannels >= 2) { - Channel->SetPids(Vpid, Ppid, Vtype, Apids, Atypes, ALangs, Dpids, Dtypes, DLangs, Spids, SLangs, Tpid); -+ if (NumTPages < MAXTXTPAGES) { -+ int manualPageNumber = cVDRTtxtsubsHookListener::Hook()->ManualPageNumber(Channel); -+ if (manualPageNumber) -+ TeletextSubtitlePages[NumTPages++] = tTeletextSubtitlePage(manualPageNumber); -+ } -+ Channel->SetTeletextSubtitlePages(TeletextSubtitlePages, NumTPages); - Channel->SetCaIds(CaDescriptors->CaIds()); - Channel->SetSubtitlingDescriptors(SubtitlingTypes, CompositionPageIds, AncillaryPageIds); - } -diff --git a/po/ca_ES.po b/po/ca_ES.po -index 8ea7bd3..5554051 100644 ---- a/po/ca_ES.po -+++ b/po/ca_ES.po -@@ -1059,6 +1059,9 @@ msgstr "Transpar - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Transparència fons subtítols" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "Configuració de l'LNB" - -diff --git a/po/cs_CZ.po b/po/cs_CZ.po -index 6c5ac1b..91625a8 100644 ---- a/po/cs_CZ.po -+++ b/po/cs_CZ.po -@@ -1059,6 +1059,9 @@ msgstr "Průhlednost písma titulků" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Průhlednost pozadí titulků" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/da_DK.po b/po/da_DK.po -index d0fbbf8..6504096 100644 ---- a/po/da_DK.po -+++ b/po/da_DK.po -@@ -1056,6 +1056,9 @@ msgstr "Undertekst forgrundsgennemsigtighed" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Undertekst baggrundsgennemsigtighed" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/de_DE.po b/po/de_DE.po -index 762c6fa..0e28962 100644 ---- a/po/de_DE.po -+++ b/po/de_DE.po -@@ -1057,6 +1057,9 @@ msgstr "Untertitel-Transparenz Vordergrund" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Untertitel-Transparenz Hintergrund" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "Videotext-Unterstützung aktivieren" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/el_GR.po b/po/el_GR.po -index a131cd7..6f131a3 100644 ---- a/po/el_GR.po -+++ b/po/el_GR.po -@@ -1056,6 +1056,9 @@ msgstr "" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/es_ES.po b/po/es_ES.po -index b2827b5..139da7a 100644 ---- a/po/es_ES.po -+++ b/po/es_ES.po -@@ -1057,6 +1057,9 @@ msgstr "Transparencia primer plano subt - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Transparencia fondo subtítulos" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/et_EE.po b/po/et_EE.po -index 8bf931a..a4c9a09 100644 ---- a/po/et_EE.po -+++ b/po/et_EE.po -@@ -1056,6 +1056,9 @@ msgstr "Subtiitri läbipaistvus" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Subtiitri tausta läbipaistvus" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "Teleteksti tugi" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/fi_FI.po b/po/fi_FI.po -index 05d4b0f..9d55f39 100644 ---- a/po/fi_FI.po -+++ b/po/fi_FI.po -@@ -1060,6 +1060,9 @@ msgstr "Tekstityksen läpinäkyvyys" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Tekstityksen taustan läpinäkyvyys" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "Salli teksti-TV-tuki" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/fr_FR.po b/po/fr_FR.po -index 06bb125..d3276f5 100644 ---- a/po/fr_FR.po -+++ b/po/fr_FR.po -@@ -1067,6 +1067,9 @@ msgstr "Transparence de l'avant-plan des sous-titres" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Transparence du fond des sous-titres" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/hr_HR.po b/po/hr_HR.po -index 0424a44..109af41 100644 ---- a/po/hr_HR.po -+++ b/po/hr_HR.po -@@ -1058,6 +1058,9 @@ msgstr "Transparentnost titla" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Transparentnost pozadine titla" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/hu_HU.po b/po/hu_HU.po -index c34bc0e..32a0ee3 100644 ---- a/po/hu_HU.po -+++ b/po/hu_HU.po -@@ -1061,6 +1061,9 @@ msgstr "Felirat transzparenciája" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Felirat hátterének transzparenciája" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/it_IT.po b/po/it_IT.po -index 79946ff..0b93c4a 100644 ---- a/po/it_IT.po -+++ b/po/it_IT.po -@@ -1062,6 +1062,9 @@ msgstr "Trasparenza sottotitoli" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Trasparenza sfondo sottotitoli" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/lt_LT.po b/po/lt_LT.po -index a77dfcc..3ad927d 100644 ---- a/po/lt_LT.po -+++ b/po/lt_LT.po -@@ -1056,6 +1056,9 @@ msgstr "Subtitrų fonto permatomumas" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Subtitrų fono permatomumas" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "Konverteris (LNB)" - -diff --git a/po/nl_NL.po b/po/nl_NL.po -index ab3fabd..b6e1a10 100644 ---- a/po/nl_NL.po -+++ b/po/nl_NL.po -@@ -1062,6 +1062,9 @@ msgstr "Transparantie voorgrond ondertiteling" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Transparantie achtergrond ondertiteling" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/nn_NO.po b/po/nn_NO.po -index ba20fc6..11ce81e 100644 ---- a/po/nn_NO.po -+++ b/po/nn_NO.po -@@ -1057,6 +1057,9 @@ msgstr "" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/pl_PL.po b/po/pl_PL.po -index becb8cb..9addb46 100644 ---- a/po/pl_PL.po -+++ b/po/pl_PL.po -@@ -1059,6 +1059,9 @@ msgstr "Prze - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Prze¼rocze podtytu³ów: T³o" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/pt_PT.po b/po/pt_PT.po -index 9a0f792..6a11cda 100644 ---- a/po/pt_PT.po -+++ b/po/pt_PT.po -@@ -1057,6 +1057,9 @@ msgstr "Transpar - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Transparência de fundo das legendas" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/ro_RO.po b/po/ro_RO.po -index c88dd0a..4f67d1c 100644 ---- a/po/ro_RO.po -+++ b/po/ro_RO.po -@@ -1058,6 +1058,9 @@ msgstr "TransparenÅ£a prim-planului subtitrării" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "TransparenÅ£a fundalului subtitrării" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/ru_RU.po b/po/ru_RU.po -index 3e5057d..5d50264 100644 ---- a/po/ru_RU.po -+++ b/po/ru_RU.po -@@ -1057,6 +1057,9 @@ msgstr " - msgid "Setup.DVB$Subtitle background transparency" - msgstr "¿àÞ×àÐçÝÞáâì äÞÝÐ áãÑâØâàÞÒ" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "ºÞÝÒÕàâÕà" - -diff --git a/po/sk_SK.po b/po/sk_SK.po -index cfc9bde..4fa36d0 100644 ---- a/po/sk_SK.po -+++ b/po/sk_SK.po -@@ -1057,6 +1057,9 @@ msgstr "Prieh - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Priehµadnos» pozadia titulkov" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB (nízko ¹umová jednotka)" - -diff --git a/po/sl_SI.po b/po/sl_SI.po -index d12ccb2..dd86028 100644 ---- a/po/sl_SI.po -+++ b/po/sl_SI.po -@@ -1057,6 +1057,9 @@ msgstr "Transparentnost podnapisov" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Transparentnost ozadja podnapisov" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/sv_SE.po b/po/sv_SE.po -index c164fa1..1c07570 100644 ---- a/po/sv_SE.po -+++ b/po/sv_SE.po -@@ -1061,6 +1061,9 @@ msgstr "Transparent f - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Transparent bakgrund textremsa" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/tr_TR.po b/po/tr_TR.po -index 46a6a08..b4a8c55 100644 ---- a/po/tr_TR.po -+++ b/po/tr_TR.po -@@ -1056,6 +1056,9 @@ msgstr "Altyaz - msgid "Setup.DVB$Subtitle background transparency" - msgstr "Altyazý arka þeffaflýk" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "LNB" - -diff --git a/po/uk_UA.po b/po/uk_UA.po -index 9d7328b..feba2ca 100644 ---- a/po/uk_UA.po -+++ b/po/uk_UA.po -@@ -1057,6 +1057,9 @@ msgstr "ПрозоріÑть переднього плану Ñубтитрів" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "ПрозоріÑть заднього плану Ñубтитрів" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "Конвертер" - -diff --git a/po/zh_CN.po b/po/zh_CN.po -index 0dfbd6c..9c16c46 100644 ---- a/po/zh_CN.po -+++ b/po/zh_CN.po -@@ -1058,6 +1058,9 @@ msgstr "字幕剿™¯é€æ˜Žåº¦" - msgid "Setup.DVB$Subtitle background transparency" - msgstr "å­—å¹•èƒŒæ™¯é€æ˜Žåº¦" - -+msgid "Setup.DVB$Enable teletext support" -+msgstr "" -+ - msgid "LNB" - msgstr "切æ¢å™¨è®¾ç½®" - -diff --git a/receiver.c b/receiver.c -index d8f51e6..7e1c252 100644 ---- a/receiver.c -+++ b/receiver.c -@@ -72,7 +72,8 @@ bool cReceiver::SetPids(const cChannel *Channel) - (Channel->Ppid() == Channel->Vpid() || AddPid(Channel->Ppid())) && - AddPids(Channel->Apids()) && - AddPids(Channel->Dpids()) && -- AddPids(Channel->Spids()); -+ AddPids(Channel->Spids()) && -+ (!Setup.SupportTeletext || AddPid(Channel->Tpid())); - } - return true; - } -diff --git a/remux.c b/remux.c -index 23e8387..f1bf562 100644 ---- a/remux.c -+++ b/remux.c -@@ -416,6 +416,29 @@ int cPatPmtGenerator::MakeSubtitlingDescriptor(uchar *Target, const char *Langua - return i; - } - -+int cPatPmtGenerator::MakeTeletextDescriptor(uchar *Target, const tTeletextSubtitlePage *pages, int pageCount) -+{ -+ int i = 0, j = 0; -+ Target[i++] = SI::TeletextDescriptorTag; -+ int l = i; -+ Target[i++] = 0x00; // length -+ for (int n = 0; n < pageCount; n++) { -+ const char* Language = pages[n].ttxtLanguage; -+ Target[i++] = *Language++; -+ Target[i++] = *Language++; -+ Target[i++] = *Language++; -+ Target[i++] = (pages[n].ttxtType << 3) + pages[n].ttxtMagazine; -+ Target[i++] = pages[n].ttxtPage; -+ j++; -+ } -+ if (j > 0) { -+ Target[l] = j * 5; // update length -+ IncEsInfoLength(i); -+ return i; -+ } -+ return 0; -+} -+ - int cPatPmtGenerator::MakeLanguageDescriptor(uchar *Target, const char *Language) - { - int i = 0; -@@ -503,6 +526,7 @@ void cPatPmtGenerator::GeneratePmt(const cChannel *Channel) - if (Channel) { - int Vpid = Channel->Vpid(); - int Ppid = Channel->Ppid(); -+ int Tpid = Channel->Tpid(); - uchar *p = buf; - int i = 0; - p[i++] = 0x02; // table id -@@ -535,6 +559,10 @@ void cPatPmtGenerator::GeneratePmt(const cChannel *Channel) - i += MakeStream(buf + i, 0x06, Channel->Spid(n)); - i += MakeSubtitlingDescriptor(buf + i, Channel->Slang(n), Channel->SubtitlingType(n), Channel->CompositionPageId(n), Channel->AncillaryPageId(n)); - } -+ if (Tpid) { -+ i += MakeStream(buf + i, 0x06, Tpid); -+ i += MakeTeletextDescriptor(buf + i, Channel->TeletextSubtitlePages(), Channel->TotalTeletextSubtitlePages()); -+ } - - int sl = i - SectionLength - 2 + 4; // -2 = SectionLength storage, +4 = length of CRC - buf[SectionLength] |= (sl >> 8) & 0x0F; -@@ -608,6 +636,7 @@ void cPatPmtParser::Reset(void) - pmtPids[0] = 0; - vpid = vtype = 0; - ppid = 0; -+ tpid = 0; - } - - void cPatPmtParser::ParsePat(const uchar *Data, int Length) -@@ -696,11 +725,13 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length) - int NumSpids = 0; - vpid = vtype = 0; - ppid = 0; -+ tpid = 0; - apids[0] = 0; - dpids[0] = 0; - spids[0] = 0; - atypes[0] = 0; - dtypes[0] = 0; -+ totalTtxtSubtitlePages = 0; - SI::PMT::Stream stream; - for (SI::Loop::Iterator it; Pmt.streamLoop.getNext(stream, it); ) { - dbgpatpmt(" stream type = %02X, pid = %d", stream.getStreamType(), stream.getPid()); -@@ -799,6 +830,28 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length) - spids[NumSpids] = 0; - } - break; -+ case SI::TeletextDescriptorTag: { -+ dbgpatpmt(" teletext"); -+ tpid = stream.getPid(); -+ SI::TeletextDescriptor *sd = (SI::TeletextDescriptor *)d; -+ SI::TeletextDescriptor::Teletext ttxt; -+ if (totalTtxtSubtitlePages < MAXTXTPAGES) { -+ for (SI::Loop::Iterator it; sd->teletextLoop.getNext(ttxt, it); ) { -+ bool isSubtitlePage = (ttxt.getTeletextType() == 0x02) || (ttxt.getTeletextType() == 0x05); -+ if (isSubtitlePage && ttxt.languageCode[0]) { -+ dbgpatpmt(" '%s:%x.%x'", ttxt.languageCode, ttxt.getTeletextMagazineNumber(), ttxt.getTeletextPageNumber()); -+ strn0cpy(teletextSubtitlePages[totalTtxtSubtitlePages].ttxtLanguage, I18nNormalizeLanguageCode(ttxt.languageCode), MAXLANGCODE1); -+ teletextSubtitlePages[totalTtxtSubtitlePages].ttxtPage = ttxt.getTeletextPageNumber(); -+ teletextSubtitlePages[totalTtxtSubtitlePages].ttxtMagazine = ttxt.getTeletextMagazineNumber(); -+ teletextSubtitlePages[totalTtxtSubtitlePages].ttxtType = ttxt.getTeletextType(); -+ totalTtxtSubtitlePages++; -+ if (totalTtxtSubtitlePages >= MAXTXTPAGES) -+ break; -+ } -+ } -+ } -+ } -+ break; - case SI::ISO639LanguageDescriptorTag: { - SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d; - dbgpatpmt(" '%s'", ld->languageCode); -diff --git a/remux.h b/remux.h -index 6bc91ad..039525d 100644 ---- a/remux.h -+++ b/remux.h -@@ -302,6 +302,7 @@ protected: - int MakeStream(uchar *Target, uchar Type, int Pid); - int MakeAC3Descriptor(uchar *Target, uchar Type); - int MakeSubtitlingDescriptor(uchar *Target, const char *Language, uchar SubtitlingType, uint16_t CompositionPageId, uint16_t AncillaryPageId); -+ int MakeTeletextDescriptor(uchar *Target, const tTeletextSubtitlePage *pages, int pageCount); - int MakeLanguageDescriptor(uchar *Target, const char *Language); - int MakeCRC(uchar *Target, const uchar *Data, int Length); - void GeneratePmtPid(const cChannel *Channel); -@@ -349,6 +350,7 @@ private: - int vpid; - int ppid; - int vtype; -+ int tpid; - int apids[MAXAPIDS + 1]; // list is zero-terminated - int atypes[MAXAPIDS + 1]; // list is zero-terminated - char alangs[MAXAPIDS][MAXLANGCODE2]; -@@ -361,6 +363,8 @@ private: - uint16_t compositionPageIds[MAXSPIDS]; - uint16_t ancillaryPageIds[MAXSPIDS]; - bool updatePrimaryDevice; -+ int totalTtxtSubtitlePages; -+ tTeletextSubtitlePage teletextSubtitlePages[MAXTXTPAGES]; - protected: - int SectionLength(const uchar *Data, int Length) { return (Length >= 3) ? ((int(Data[1]) & 0x0F) << 8)| Data[2] : 0; } - public: -@@ -397,6 +401,9 @@ public: - int Vtype(void) const { return vtype; } - ///< Returns the video stream type as defined by the current PMT, or 0 if no video - ///< stream type has been detected, yet. -+ int Tpid(void) { return tpid; } -+ ///< Returns the teletext pid as defined by the current PMT, or 0 if no teletext -+ ///< pid has been detected, yet. - const int *Apids(void) const { return apids; } - const int *Dpids(void) const { return dpids; } - const int *Spids(void) const { return spids; } -@@ -411,6 +418,8 @@ public: - uchar SubtitlingType(int i) const { return (0 <= i && i < MAXSPIDS) ? subtitlingTypes[i] : uchar(0); } - uint16_t CompositionPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? compositionPageIds[i] : uint16_t(0); } - uint16_t AncillaryPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? ancillaryPageIds[i] : uint16_t(0); } -+ const tTeletextSubtitlePage *TeletextSubtitlePages() const { return teletextSubtitlePages; } -+ int TotalTeletextSubtitlePages() const { return totalTtxtSubtitlePages; } - }; - - // TS to PES converter: -diff --git a/vdr.5 b/vdr.5 -index fa233d7..cc06655 100644 ---- a/vdr.5 -+++ b/vdr.5 -@@ -249,6 +249,12 @@ by an '=' sign, as in - - .B ...:201;2001=deu,2002=eng:... - -+Manual teletext subtitling pages can be defined separated by a '+' sign. -+The pages (separated by commas) can contain language codes, delimited by a '=' -+sign, as in -+ -+.B ...:201+150=deu,151=fin;2001,2002:... -+ - .TP - .B Conditional access - A hexadecimal integer defining how this channel can be accessed: -diff --git a/vdrttxtsubshooks.c b/vdrttxtsubshooks.c -new file mode 100644 -index 0000000..2471788 ---- /dev/null -+++ b/vdrttxtsubshooks.c -@@ -0,0 +1,63 @@ -+/* -+ * vdr-ttxtsubs - A plugin for the Linux Video Disk Recorder -+ * Copyright (c) 2003 - 2008 Ragnar Sundblad -+ * -+ * 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 the -+ * Free Software Foundation; either version 2 of the License, or (at your option) -+ * any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ * -+ */ -+ -+#include -+#include -+#include -+ -+#include "vdrttxtsubshooks.h" -+ -+// XXX Really should be a list... -+static cVDRTtxtsubsHookListener *gListener; -+ -+// ------ class cVDRTtxtsubsHookProxy ------ -+ -+class cVDRTtxtsubsHookProxy : public cVDRTtxtsubsHookListener -+{ -+ public: -+ virtual void HideOSD(void) { if(gListener) gListener->HideOSD(); }; -+ virtual void ShowOSD(void) { if(gListener) gListener->ShowOSD(); }; -+ virtual void PlayerTeletextData(uint8_t *p, int length, bool IsPesRecording, const struct tTeletextSubtitlePage teletextSubtitlePages[] = NULL, int pageCount = 0) -+ { if(gListener) gListener->PlayerTeletextData(p, length, IsPesRecording, teletextSubtitlePages, pageCount); }; -+ virtual int ManualPageNumber(const cChannel *channel) -+ { if(gListener) return gListener->ManualPageNumber(channel); else return 0; }; -+}; -+ -+ -+// ------ class cVDRTtxtsubsHookListener ------ -+ -+cVDRTtxtsubsHookListener::~cVDRTtxtsubsHookListener() -+{ -+ gListener = 0; -+} -+ -+void cVDRTtxtsubsHookListener::HookAttach(void) -+{ -+ gListener = this; -+ //printf("cVDRTtxtsubsHookListener::HookAttach\n"); -+} -+ -+static cVDRTtxtsubsHookProxy gProxy; -+ -+cVDRTtxtsubsHookListener *cVDRTtxtsubsHookListener::Hook(void) -+{ -+ return &gProxy; -+} -+ -diff --git a/vdrttxtsubshooks.h b/vdrttxtsubshooks.h -new file mode 100644 -index 0000000..2f97969 ---- /dev/null -+++ b/vdrttxtsubshooks.h -@@ -0,0 +1,46 @@ -+/* -+ * vdr-ttxtsubs - A plugin for the Linux Video Disk Recorder -+ * Copyright (c) 2003 - 2008 Ragnar Sundblad -+ * -+ * 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 the -+ * Free Software Foundation; either version 2 of the License, or (at your option) -+ * any later version. -+ * -+ * This program is distributed in the hope that it will be useful, but -+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -+ * details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ * -+ */ -+ -+#ifndef __VDRTTXTSUBSHOOKS_H -+#define __VDRTTXTSUBSHOOKS_H -+ -+#define TTXTSUBSVERSNUM 2 -+ -+class cDevice; -+class cChannel; -+struct tTeletextSubtitlePage; -+ -+class cVDRTtxtsubsHookListener { -+ public: -+ cVDRTtxtsubsHookListener(void) {}; -+ virtual ~cVDRTtxtsubsHookListener(); -+ -+ void HookAttach(void); -+ -+ virtual void HideOSD(void) {}; -+ virtual void ShowOSD(void) {}; -+ virtual void PlayerTeletextData(uint8_t *p, int length, bool IsPesRecording = true, const struct tTeletextSubtitlePage teletextSubtitlePages[] = NULL, int pageCount = 0) {}; -+ virtual int ManualPageNumber(const cChannel *channel) { return 0; }; -+ -+ // used by VDR to call hook listeners -+ static cVDRTtxtsubsHookListener *Hook(void); -+}; -+ -+#endif diff --git a/vdr-2.3.2-unsignedtosigned.diff b/vdr-2.3.2-unsignedtosigned.diff deleted file mode 100644 index e4acd09..0000000 --- a/vdr-2.3.2-unsignedtosigned.diff +++ /dev/null @@ -1,102 +0,0 @@ ---- a/diseqc.c 2015/01/26 12:02:14 4.0 -+++ b/diseqc.c 2017/01/09 15:10:40 -@@ -253,10 +253,10 @@ - return result; - } - --uint cDiseqc::SetScrFrequency(uint SatFrequency, const cScr *Scr, uint8_t *Codes) const -+int cDiseqc::SetScrFrequency(int SatFrequency, const cScr *Scr, uint8_t *Codes) const - { - if ((Codes[0] & 0xF0) == 0x70 ) { // EN50607 aka JESS -- uint t = SatFrequency == 0 ? 0 : (SatFrequency - 100); -+ int t = SatFrequency == 0 ? 0 : (SatFrequency - 100); - if (t < 2048 && Scr->Channel() >= 0 && Scr->Channel() < 32) { - Codes[1] = t >> 8 | Scr->Channel() << 3; - Codes[2] = t; -@@ -266,7 +266,7 @@ - } - } - else { // EN50494 aka Unicable -- uint t = SatFrequency == 0 ? 0 : (SatFrequency + Scr->UserBand() + 2) / 4 - 350; // '+ 2' together with '/ 4' results in rounding! -+ int t = SatFrequency == 0 ? 0 : (SatFrequency + Scr->UserBand() + 2) / 4 - 350; // '+ 2' together with '/ 4' results in rounding! - if (t < 1024 && Scr->Channel() >= 0 && Scr->Channel() < 8) { - Codes[3] = t >> 8 | (t == 0 ? 0 : scrBank << 2) | Scr->Channel() << 5; - Codes[4] = t; -@@ -399,7 +399,7 @@ - return NULL; - } - --cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, uint *Frequency) const -+cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, int *Frequency) const - { - if (!*CurrentAction) - *CurrentAction = commands; ---- a/diseqc.h 2013/06/12 11:52:17 4.0 -+++ b/diseqc.h 2017/01/09 15:11:19 -@@ -86,7 +86,7 @@ - mutable int scrBank; - char *commands; - bool parsing; -- uint SetScrFrequency(uint SatFrequency, const cScr *Scr, uint8_t *Codes) const; -+ int SetScrFrequency(int SatFrequency, const cScr *Scr, uint8_t *Codes) const; - int SetScrPin(const cScr *Scr, uint8_t *Codes) const; - const char *Wait(const char *s) const; - const char *GetPosition(const char *s) const; -@@ -96,7 +96,7 @@ - cDiseqc(void); - ~cDiseqc(); - bool Parse(const char *s); -- eDiseqcActions Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, uint *Frequency) const; -+ eDiseqcActions Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, int *Frequency) const; - ///< Parses the DiSEqC commands and returns the appropriate action code - ///< with every call. CurrentAction must be the address of a character pointer, - ///< which is initialized to NULL. This pointer is used internally while parsing ---- a/dvbdevice.c 2016/11/07 13:55:58 4.3 -+++ b/dvbdevice.c 2017/01/09 15:11:39 -@@ -329,7 +329,7 @@ - void ClearEventQueue(void) const; - bool GetFrontendStatus(fe_status_t &Status) const; - cPositioner *GetPositioner(void); -- void ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency); -+ void ExecuteDiseqc(const cDiseqc *Diseqc, int *Frequency); - void ResetToneAndVoltage(void); - bool SetFrontend(void); - virtual void Action(void); -@@ -696,7 +696,7 @@ - return positioner; - } - --void cDvbTuner::ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency) -+void cDvbTuner::ExecuteDiseqc(const cDiseqc *Diseqc, int *Frequency) - { - if (!lnbPowerTurnedOn) { - CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // must explicitly turn on LNB power -@@ -806,7 +806,7 @@ - - SETCMD(DTV_DELIVERY_SYSTEM, frontendType); - if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2) { -- unsigned int frequency = channel.Frequency(); -+ int frequency = channel.Frequency(); - if (Setup.DiSEqC) { - if (const cDiseqc *diseqc = Diseqcs.Get(device->CardIndex() + 1, channel.Source(), frequency, dtp.Polarization(), &scr)) { - frequency -= diseqc->Lof(); -@@ -829,7 +829,7 @@ - } - else { - int tone = SEC_TONE_OFF; -- if (frequency < (unsigned int)Setup.LnbSLOF) { -+ if (frequency < Setup.LnbSLOF) { - frequency -= Setup.LnbFrequLo; - tone = SEC_TONE_OFF; - } ---- a/remux.c.orig 2017-03-02 13:22:31.133182283 +0100 -+++ b/remux.c 2017-03-02 13:23:50.300598025 +0100 -@@ -1638,7 +1638,7 @@ - Div += parser->IFrameTemporalReferenceOffset(); - if (Div <= 0) - Div = 1; -- uint32_t Delta = ptsValues[0] / Div; -+ int Delta = ptsValues[0] / Div; - // determine frame info: - if (isVideo) { - if (abs(Delta - 3600) <= 1) diff --git a/vdr-2.4.0-01-fix-svdrp-modt-recflag.diff b/vdr-2.4.0-01-fix-svdrp-modt-recflag.diff deleted file mode 100644 index cc49bd9..0000000 --- a/vdr-2.4.0-01-fix-svdrp-modt-recflag.diff +++ /dev/null @@ -1,44 +0,0 @@ -# This patch fixes a bug in handling the tfRecording flag in the SVDRP commands MODT -# and UPDT. The tfRecording flag must only be handled by the VDR that actually hosts -# and processes the timer. -# ---- svdrp.c 2018/03/19 12:16:33 5.0 -+++ svdrp.c 2018/04/19 09:45:08 -@@ -2036,6 +2036,7 @@ - LOCK_TIMERS_WRITE; - Timers->SetExplicitModify(); - if (cTimer *Timer = Timers->GetById(Id)) { -+ bool IsRecording = Timer->HasFlags(tfRecording); - cTimer t = *Timer; - if (strcasecmp(tail, "ON") == 0) - t.SetFlags(tfActive); -@@ -2046,6 +2047,10 @@ - return; - } - *Timer = t; -+ if (IsRecording) -+ Timer->SetFlags(tfRecording); -+ else -+ Timer->ClrFlags(tfRecording); - Timers->SetModified(); - isyslog("SVDRP %s < %s modified timer %s (%s)", Setup.SVDRPHostName, *clientName, *Timer->ToDescr(), Timer->HasFlags(tfActive) ? "active" : "inactive"); - Reply(250, "%d %s", Timer->Id(), *Timer->ToText(true)); -@@ -2478,12 +2483,18 @@ - if (Timer->Parse(Option)) { - LOCK_TIMERS_WRITE; - if (cTimer *t = Timers->GetTimer(Timer)) { -+ bool IsRecording = t->HasFlags(tfRecording); - t->Parse(Option); - delete Timer; - Timer = t; -+ if (IsRecording) -+ Timer->SetFlags(tfRecording); -+ else -+ Timer->ClrFlags(tfRecording); - isyslog("SVDRP %s < %s updated timer %s", Setup.SVDRPHostName, *clientName, *Timer->ToDescr()); - } - else { -+ Timer->ClrFlags(tfRecording); - Timers->Add(Timer); - isyslog("SVDRP %s < %s added timer %s", Setup.SVDRPHostName, *clientName, *Timer->ToDescr()); - } diff --git a/vdr-2.4.0-mainmenuhooks101.patch b/vdr-2.4.0-mainmenuhooks101.patch deleted file mode 100644 index 6680612..0000000 --- a/vdr-2.4.0-mainmenuhooks101.patch +++ /dev/null @@ -1,108 +0,0 @@ ---- vdr-2.4.0/config.h.orig 2018-04-16 09:36:30.655036427 +0200 -+++ vdr-2.4.0/config.h 2018-04-16 09:37:43.068036894 +0200 -@@ -47,6 +47,10 @@ - #define TIMERMACRO_TITLE "TITLE" - #define TIMERMACRO_EPISODE "EPISODE" - -+// The MainMenuHook Patch's version number: -+#define MAINMENUHOOKSVERSION "1.0.1" -+#define MAINMENUHOOKSVERSNUM 10001 // Version * 10000 + Major * 100 + Minor -+ - #define MINOSDWIDTH 480 - #define MAXOSDWIDTH 1920 - #define MINOSDHEIGHT 324 ---- vdr-2.4.0/menu.c.orig 2018-04-16 09:39:22.013037531 +0200 -+++ vdr-2.4.0/menu.c 2018-04-16 10:24:50.584055109 +0200 -@@ -4475,16 +4475,31 @@ - Set(); - - // Initial submenus: -- -+ cOsdObject *menu = NULL; - switch (State) { -- case osSchedule: AddSubMenu(new cMenuSchedule); break; -- case osChannels: AddSubMenu(new cMenuChannels); break; -- case osTimers: AddSubMenu(new cMenuTimers); break; -- case osRecordings: AddSubMenu(new cMenuRecordings(NULL, 0, OpenSubMenus)); break; -- case osSetup: AddSubMenu(new cMenuSetup); break; -- case osCommands: AddSubMenu(new cMenuCommands(tr("Commands"), &Commands)); break; -+ case osSchedule: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu)) -+ menu = new cMenuSchedule; -+ break; -+ case osChannels: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu)) -+ menu = new cMenuChannels; -+ break; -+ case osTimers: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu)) -+ menu = new cMenuTimers; -+ break; -+ case osRecordings: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu)) -+ menu = new cMenuRecordings(NULL, 0, OpenSubMenus); -+ break; -+ case osSetup: menu = new cMenuSetup; break; -+ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break; - default: break; - } -+ if (menu) -+ if (menu->IsMenu()) -+ AddSubMenu((cOsdMenu *) menu); - } - - cOsdObject *cMenuMain::PluginOsdObject(void) -@@ -4592,13 +4607,34 @@ - eOSState state = cOsdMenu::ProcessKey(Key); - HadSubMenu |= HasSubMenu(); - -+ cOsdObject *menu = NULL; - switch (state) { -- case osSchedule: return AddSubMenu(new cMenuSchedule); -- case osChannels: return AddSubMenu(new cMenuChannels); -- case osTimers: return AddSubMenu(new cMenuTimers); -- case osRecordings: return AddSubMenu(new cMenuRecordings); -- case osSetup: return AddSubMenu(new cMenuSetup); -- case osCommands: return AddSubMenu(new cMenuCommands(tr("Commands"), &Commands)); -+ case osSchedule: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu)) -+ menu = new cMenuSchedule; -+ else -+ state = osContinue; -+ break; -+ case osChannels: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu)) -+ menu = new cMenuChannels; -+ else -+ state = osContinue; -+ break; -+ case osTimers: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu)) -+ menu = new cMenuTimers; -+ else -+ state = osContinue; -+ break; -+ case osRecordings: -+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu)) -+ menu = new cMenuRecordings; -+ else -+ state = osContinue; -+ break; -+ case osSetup: menu = new cMenuSetup; break; -+ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break; - case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) { - if (cOsdItem *item = Get(Current())) { - cRecordControls::Stop(item->Text() + strlen(tr(STOP_RECORDING))); -@@ -4649,6 +4685,12 @@ - default: break; - } - } -+ if (menu) { -+ if (menu->IsMenu()) -+ return AddSubMenu((cOsdMenu *) menu); -+ pluginOsdObject = menu; -+ return osPlugin; -+ } - if (!HasSubMenu() && Update(HadSubMenu)) - Display(); - if (Key != kNone) { diff --git a/vdr-2.4.1-glibc231.patch b/vdr-2.4.1-glibc231.patch deleted file mode 100644 index 528d210..0000000 --- a/vdr-2.4.1-glibc231.patch +++ /dev/null @@ -1,24 +0,0 @@ -From dcfa8ba29f4c95edbdceb0f1bbae0e62fa40c4e2 Mon Sep 17 00:00:00 2001 -From: Manuel Reimer -Date: Sat, 14 Dec 2019 12:01:13 +0100 -Subject: [PATCH] Replace obsolete stime() function with clock_settime() - ---- - eit.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/eit.c b/eit.c -index 50d8229..82294dc 100644 ---- a/eit.c -+++ b/eit.c -@@ -391,7 +391,9 @@ cTDT::cTDT(const u_char *Data) - if (abs(diff) > MAX_TIME_DIFF) { - mutex.Lock(); - if (abs(diff) > MAX_ADJ_DIFF) { -- if (stime(&dvbtim) == 0) -+ 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); - else - esyslog("ERROR while setting system time: %m"); diff --git a/vdr-2.4.1-mark-obsolete-NidTid.patch b/vdr-2.4.1-mark-obsolete-NidTid.patch deleted file mode 100644 index 12b51b6..0000000 --- a/vdr-2.4.1-mark-obsolete-NidTid.patch +++ /dev/null @@ -1,115 +0,0 @@ -diff -Nurp vdr-2.4.1.orig/channels.c vdr-2.4.1.NitTid/channels.c ---- vdr-2.4.1.orig/channels.c 2017-06-10 17:08:56.000000000 +0200 -+++ vdr-2.4.1.NitTid/channels.c 2019-09-24 20:48:49.243342312 +0200 -@@ -1096,11 +1096,13 @@ cChannel *cChannels::NewChannel(const cC - #define CHANNELMARKOBSOLETE "OBSOLETE" - #define CHANNELTIMEOBSOLETE 3600 // seconds to wait before declaring a channel obsolete (in case it has actually been seen before) - --bool cChannels::MarkObsoleteChannels(int Source, int Nid, int Tid) -+bool cChannels::MarkObsoleteChannels(int Source, int Nid, int Tid, int Transponder) - { - bool ChannelsModified = false; - for (cChannel *Channel = First(); Channel; Channel = Next(Channel)) { - if (time(NULL) - Channel->Seen() > CHANNELTIMEOBSOLETE && Channel->Source() == Source && Channel->Nid() == Nid && Channel->Tid() == Tid && Channel->Rid() == 0) { -+ if (Transponder && !ISTRANSPONDER(Channel->Transponder(), Transponder)) // mark channels only on specified transponder -+ continue; - int OldShowChannelNamesWithSource = Setup.ShowChannelNamesWithSource; - Setup.ShowChannelNamesWithSource = 0; - if (!endswith(Channel->Name(), CHANNELMARKOBSOLETE)) -diff -Nurp vdr-2.4.1.orig/channels.h vdr-2.4.1.NitTid/channels.h ---- vdr-2.4.1.orig/channels.h 2017-06-10 17:06:40.000000000 +0200 -+++ vdr-2.4.1.NitTid/channels.h 2019-09-23 22:46:20.231197911 +0200 -@@ -251,7 +251,7 @@ public: - ///< and will be set to the current value of the list's internal state variable upon - ///< return from this function. - cChannel *NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid = 0); -- bool MarkObsoleteChannels(int Source, int Nid, int Tid); -+ bool MarkObsoleteChannels(int Source, int Nid, int Tid, int Transponder = 0); - }; - - // Provide lock controlled access to the list: -diff -Nurp vdr-2.4.1.orig/eitscan.c vdr-2.4.1.NitTid/eitscan.c ---- vdr-2.4.1.orig/eitscan.c 2019-03-12 12:54:27.000000000 +0100 -+++ vdr-2.4.1.NitTid/eitscan.c 2019-09-23 23:31:26.778124945 +0200 -@@ -60,8 +60,11 @@ void cScanList::AddTransponder(const cCh - { - if (Channel->Source() && Channel->Transponder()) { - for (cScanData *sd = First(); sd; sd = Next(sd)) { -- if (sd->Source() == Channel->Source() && ISTRANSPONDER(sd->Transponder(), Channel->Transponder())) -- return; -+ if (sd->Source() == Channel->Source() && ISTRANSPONDER(sd->Transponder(), Channel->Transponder())) { -+ const cChannel *ch = sd->GetChannel(); -+ if (ch->Nid() == Channel->Nid() && ch->Tid() == Channel->Tid()) // add a channel for each unique transponder/Nid/Tid triple -+ return; -+ } - } - Add(new cScanData(Channel)); - } -@@ -78,8 +81,10 @@ void cTransponderList::AddTransponder(cC - { - for (cChannel *ch = First(); ch; ch = Next(ch)) { - if (ch->Source() == Channel->Source() && ch->Transponder() == Channel->Transponder()) { -- delete Channel; -- return; -+ if (ch->Nid() == Channel->Nid() && ch->Tid() == Channel->Tid()) { // add a channel for each unique transponder/Nid/Tid triple -+ delete Channel; -+ return; -+ } - } - } - Add(Channel); -diff -Nurp vdr-2.4.1.orig/nit.c vdr-2.4.1.NitTid/nit.c ---- vdr-2.4.1.orig/nit.c 2019-05-31 23:47:02.000000000 +0200 -+++ vdr-2.4.1.NitTid/nit.c 2019-09-25 00:09:04.140501158 +0200 -@@ -107,6 +107,7 @@ void cNitFilter::Process(u_short Pid, u_ - } - - for (SI::Loop::Iterator it2; (d = ts.transportStreamDescriptors.getNext(it2)); ) { -+ int tsTransponder = 0; - switch (d->getDescriptorTag()) { - case SI::SatelliteDeliverySystemDescriptorTag: { - SI::SatelliteDeliverySystemDescriptor *sd = (SI::SatelliteDeliverySystemDescriptor *)d; -@@ -125,6 +126,7 @@ void cNitFilter::Process(u_short Pid, u_ - dtp.SetRollOff(System ? RollOffs[sd->getRollOff()] : ROLLOFF_AUTO); - int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10; - dbgnit(" %s %d %c %d %d DVB-S%d\n", *cSource::ToString(Source), Frequency, dtp.Polarization(), SymbolRate, cChannel::Transponder(Frequency, dtp.Polarization()), System ? 2 : 1); -+ tsTransponder = cChannel::Transponder(Frequency, dtp.Polarization()); - if (Setup.UpdateChannels >= 5) { - bool found = false; - bool forceTransponderUpdate = false; -@@ -192,6 +194,7 @@ void cNitFilter::Process(u_short Pid, u_ - dtp.SetModulation(Modulations[min(sd->getModulation(), 6)]); - int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10; - dbgnit(" %s %d %d %d %d\n", *cSource::ToString(Source), Frequency, dtp.CoderateH(), dtp.Modulation(), SymbolRate); -+ tsTransponder = Frequency / 1000; - if (Setup.UpdateChannels >= 5) { - bool found = false; - bool forceTransponderUpdate = false; -@@ -248,6 +251,7 @@ void cNitFilter::Process(u_short Pid, u_ - static int TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_4K, TRANSMISSION_MODE_AUTO }; - dtp.SetTransmission(TransmissionModes[sd->getTransmissionMode()]); - dbgnit(" %s %d %d %d %d %d %d %d %d\n", *cSource::ToString(Source), Frequency, dtp.Bandwidth(), dtp.Modulation(), dtp.Hierarchy(), dtp.CoderateH(), dtp.CoderateL(), dtp.Guard(), dtp.Transmission()); -+ tsTransponder = Frequency / 1000000; - if (Setup.UpdateChannels >= 5) { - bool found = false; - bool forceTransponderUpdate = false; -@@ -298,6 +302,7 @@ void cNitFilter::Process(u_short Pid, u_ - SI::ExtensionDescriptor *sd = (SI::ExtensionDescriptor *)d; - switch (sd->getExtensionDescriptorTag()) { - case SI::T2DeliverySystemDescriptorTag: { -+ tsTransponder = Transponder(); - if (Setup.UpdateChannels >= 5) { - for (cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) { - int Source = cSource::FromData(cSource::stTerr); -@@ -368,6 +373,11 @@ void cNitFilter::Process(u_short Pid, u_ - break; - default: ; - } -+ if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3) { -+ // mark all channels with obsolete Nid/Tid on tuned transponder -+ if (tsTransponder && ISTRANSPONDER(tsTransponder, Transponder()) && (Channel()->Nid() != ts.getOriginalNetworkId() || Channel()->Tid() != ts.getTransportStreamId())) -+ ChannelsModified |= Channels->MarkObsoleteChannels(Source(), Channel()->Nid(), Channel()->Tid(), Transponder()); -+ } - delete d; - } - } diff --git a/vdr-2.4.1-skincurses-log-errors.patch b/vdr-2.4.1-skincurses-log-errors.patch deleted file mode 100644 index 593be22..0000000 --- a/vdr-2.4.1-skincurses-log-errors.patch +++ /dev/null @@ -1,22 +0,0 @@ - -Description: Log an error message when skincures can't initialize the screen -Author: Tobias Grimm - ---- a/PLUGINS/src/skincurses/skincurses.c.orig 2019-06-17 18:31:59.351079418 +0200 -+++ b/PLUGINS/src/skincurses/skincurses.c 2019-06-17 18:35:21.586034302 +0200 -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - - static const char *VERSION = "2.4.1"; - static const char *DESCRIPTION = trNOOP("A text only skin"); -@@ -841,6 +842,7 @@ - ScOsdHeight = maxy - begy + 1; - return true; - } -+ esyslog("skincurses: unable to initialize curses screen"); - return false; - } - diff --git a/vdr-2.4.4-RecordingInfo.patch b/vdr-2.4.4-RecordingInfo.patch deleted file mode 100644 index 6a613f1..0000000 --- a/vdr-2.4.4-RecordingInfo.patch +++ /dev/null @@ -1,62 +0,0 @@ -diff --git a/recording.h b/recording.h -index 6f26f2f6..718df343 100644 ---- a/recording.h -+++ b/recording.h -@@ -41,6 +41,11 @@ enum eRecordingUsage { - ruCanceled = 0x8000, // the operation has been canceled, waiting for cleanup - }; - -+// workaround patch for enabling extra features in extrecmenung until vdr 2.5.2 is released -+#ifndef EPGRENAME -+#define EPGRENAME -+#endif -+ - void RemoveDeletedRecordings(void); - void AssertFreeDiskSpace(int Priority = 0, bool Force = false); - ///< The special Priority value -1 means that we shall get rid of any -@@ -74,8 +79,6 @@ private: - char *fileName; - cRecordingInfo(const cChannel *Channel = NULL, const cEvent *Event = NULL); - bool Read(FILE *f); -- void SetData(const char *Title, const char *ShortText, const char *Description); -- void SetAux(const char *Aux); - public: - cRecordingInfo(const char *FileName); - ~cRecordingInfo(); -@@ -93,6 +96,8 @@ public: - bool Write(FILE *f, const char *Prefix = "") const; - bool Read(void); - bool Write(void) const; -+ void SetData(const char *Title, const char *ShortText, const char *Description); -+ void SetAux(const char *Aux); - }; - - class cRecording : public cListObject { -@@ -150,7 +155,7 @@ public: - ///< Returns the full path name to the recording directory, including the - ///< video directory and the actual '*.rec'. For disk file access use. - const char *Title(char Delimiter = ' ', bool NewIndicator = false, int Level = -1) const; -- const cRecordingInfo *Info(void) const { return info; } -+ cRecordingInfo *Info(void) const { return info; } - const char *PrefixFileName(char Prefix); - int HierarchyLevels(void) const; - void ResetResume(void) const; -diff --git a/recording.c b/recording.c -index 17467e36..a7f08a26 100644 ---- a/recording.c -+++ b/recording.c -@@ -430,11 +430,11 @@ cRecordingInfo::~cRecordingInfo() - - void cRecordingInfo::SetData(const char *Title, const char *ShortText, const char *Description) - { -- if (!isempty(Title)) -+ if (Title) - ((cEvent *)event)->SetTitle(Title); -- if (!isempty(ShortText)) -+ if (ShortText) - ((cEvent *)event)->SetShortText(ShortText); -- if (!isempty(Description)) -+ if (Description) - ((cEvent *)event)->SetDescription(Description); - } - diff --git a/vdr-2.4.6-MarkObsoleteChannels2.diff b/vdr-2.4.6-MarkObsoleteChannels2.diff deleted file mode 100644 index a0c4185..0000000 --- a/vdr-2.4.6-MarkObsoleteChannels2.diff +++ /dev/null @@ -1,62 +0,0 @@ -diff -Nurp vdr-2.4.6.orig/channels.c vdr-2.4.6/channels.c ---- vdr-2.4.6.orig/channels.c 2020-04-11 11:22:05.000000000 +0200 -+++ vdr-2.4.6/channels.c 2021-01-01 12:35:10.946734352 +0100 -@@ -1115,11 +1116,20 @@ cChannel *cChannels::NewChannel(const cC - #define CHANNELMARKOBSOLETE "OBSOLETE" - #define CHANNELTIMEOBSOLETE 3600 // seconds to wait before declaring a channel obsolete (in case it has actually been seen before) - --bool cChannels::MarkObsoleteChannels(int Source, int Nid, int Tid) -+bool cChannels::MarkObsoleteChannels(int Source, int Transponder, int StreamId, int Nid, int Tid) - { - bool ChannelsModified = false; - for (cChannel *Channel = First(); Channel; Channel = Next(Channel)) { -- if (time(NULL) - Channel->Seen() > CHANNELTIMEOBSOLETE && Channel->Source() == Source && Channel->Nid() == Nid && Channel->Tid() == Tid && Channel->Rid() == 0) { -+ if (Channel->Source() != Source) -+ continue; -+ bool obsolete = false; -+ if (Channel->Nid() == Nid && Channel->Tid() == Tid) -+ obsolete = time(NULL) - Channel->Seen() > CHANNELTIMEOBSOLETE && Channel->Rid() == 0; // obsolete Sid -+ else if (ISTRANSPONDER(Channel->Transponder(), Transponder)) { -+ cDvbTransponderParameters dtp(Channel->Parameters()); -+ obsolete = dtp.StreamId() == StreamId; // obsolete Nid/Tid -+ } -+ if (obsolete) { - int OldShowChannelNamesWithSource = Setup.ShowChannelNamesWithSource; - Setup.ShowChannelNamesWithSource = 0; - if (!endswith(Channel->Name(), CHANNELMARKOBSOLETE)) -diff -Nurp vdr-2.4.6.orig/channels.h vdr-2.4.6/channels.h ---- vdr-2.4.6.orig/channels.h 2020-06-10 16:00:36.000000000 +0200 -+++ vdr-2.4.6/channels.h 2020-12-31 18:35:07.050191444 +0100 -@@ -252,7 +252,7 @@ public: - ///< and will be set to the current value of the list's internal state variable upon - ///< return from this function. - cChannel *NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid = 0); -- bool MarkObsoleteChannels(int Source, int Nid, int Tid); -+ bool MarkObsoleteChannels(int Source, int Transponder, int Streamid, int Nid, int Tid); - }; - - // Provide lock controlled access to the list: -diff -Nurp vdr-2.4.6.orig/sdt.c vdr-2.4.6/sdt.c ---- vdr-2.4.6.orig/sdt.c 2020-06-16 16:50:07.000000000 +0200 -+++ vdr-2.4.6/sdt.c 2020-12-31 18:40:31.853536210 +0100 -@@ -12,6 +12,7 @@ - #include "config.h" - #include "libsi/section.h" - #include "libsi/descriptor.h" -+#include "dvbdevice.h" - - // Set to 'true' for debug output: - static bool DebugSdt = false; -@@ -205,9 +206,10 @@ void cSdtFilter::Process(u_short Pid, u_ - } - if (sdt.getSectionNumber() == sdt.getLastSectionNumber()) { - if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3) { -- ChannelsModified |= Channels->MarkObsoleteChannels(source, sdt.getOriginalNetworkId(), sdt.getTransportStreamId()); -+ cDvbTransponderParameters dtp(Channel()->Parameters()); -+ ChannelsModified |= Channels->MarkObsoleteChannels(source, Transponder(), dtp.StreamId(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId()); - if (source != Source()) -- ChannelsModified |= Channels->MarkObsoleteChannels(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId()); -+ ChannelsModified |= Channels->MarkObsoleteChannels(Source(), Transponder(), dtp.StreamId(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId()); - } - } - StateKey.Remove(ChannelsModified); diff --git a/vdr-2.4.7_gcc11.patch b/vdr-2.4.7_gcc11.patch deleted file mode 100644 index 1e37b2f..0000000 --- a/vdr-2.4.7_gcc11.patch +++ /dev/null @@ -1,26 +0,0 @@ -Fix compile with gcc-11, officially from kls - -Signed-off-by: Martin Dummer - ---- a/tools.h 2021/01/19 20:38:28 5.3 -+++ b/tools.h 2021/05/05 15:16:45 -@@ -53,17 +53,15 @@ - - // In case some plugin needs to use the STL and gets an error message regarding one - // of these functions, you can #define DISABLE_TEMPLATES_COLLIDING_WITH_STL before --// including tools.h. --#if !defined(__STL_CONFIG_H) // for old versions of the STL --#if !defined(DISABLE_TEMPLATES_COLLIDING_WITH_STL) && !defined(_STL_ALGOBASE_H) -+// including any VDR header files. -+#if !defined(DISABLE_TEMPLATES_COLLIDING_WITH_STL) - template inline T min(T a, T b) { return a <= b ? a : b; } - template inline T max(T a, T b) { return a >= b ? a : b; } - #endif - template inline int sgn(T a) { return a < 0 ? -1 : a > 0 ? 1 : 0; } --#if !defined(DISABLE_TEMPLATES_COLLIDING_WITH_STL) && !defined(_MOVE_H) -+#if !defined(DISABLE_TEMPLATES_COLLIDING_WITH_STL) - template inline void swap(T &a, T &b) { T t = a; a = b; b = t; } - #endif --#endif - - template inline T constrain(T v, T l, T h) { return v < l ? l : v > h ? h : v; } diff --git a/vdr-2.6.0-eit.patch b/vdr-2.6.0-eit.patch deleted file mode 100644 index 63b581d..0000000 Binary files a/vdr-2.6.0-eit.patch and /dev/null differ diff --git a/vdr-2.6.0-fix-dvbplayer.diff b/vdr-2.6.0-fix-dvbplayer.diff deleted file mode 100644 index 38ae3d9..0000000 --- a/vdr-2.6.0-fix-dvbplayer.diff +++ /dev/null @@ -1,11 +0,0 @@ ---- a/dvbplayer.c 2019/05/27 13:54:19 5.0 -+++ b/dvbplayer.c 2022/01/13 10:18:27 -@@ -914,7 +914,7 @@ - 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 { diff --git a/vdr-2.6.2-index-file-regeneration-failed.patch b/vdr-2.6.2-index-file-regeneration-failed.patch deleted file mode 100644 index 61f140f..0000000 --- a/vdr-2.6.2-index-file-regeneration-failed.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/recording.c 2022/11/28 14:39:23 5.19 -+++ b/recording.c 2022/12/01 12:39:42 -@@ -2579,7 +2579,7 @@ - cCondWait::SleepMs(INDEXFILETESTINTERVAL); - } - int delta = 0; -- if (!Record && (access(fileName, R_OK) != 0 || FileSize(fileName) == 0)) { -+ if (!Record && (access(fileName, R_OK) != 0 || FileSize(fileName) == 0 && time(NULL) - LastModifiedTime(fileName) > MAXWAITFORINDEXFILE)) { - // Index file doesn't exist, so try to regenerate it: - if (!isPesRecording) { // sorry, can only do this for TS recordings - resumeFile.Delete(); // just in case diff --git a/vdr-2.6.2-remux.patch b/vdr-2.6.2-remux.patch deleted file mode 100644 index bf43afb..0000000 --- a/vdr-2.6.2-remux.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff --git a/remux.c b/remux.c -index 391fd6ff..54fc50fd 100644 ---- a/remux.c -+++ b/remux.c -@@ -1333,7 +1333,7 @@ int cMpeg2Parser::Parse(const uchar *Data, int Length, int Pid) - seenScanType = true; - if (debug) { - cString s = cString::sprintf("MPEG2: %d x %d%c %.2f fps", frameWidth, frameHeight, progressive ? 'p' : 'i', framesPerSecond); -- dsyslog(s); -+ dsyslog("%s",*s); - dbgframes("\n%s", *s); - } - } -@@ -1607,7 +1607,7 @@ void cH264Parser::ParseSequenceParameterSet(void) - } - if (debug) { - cString s = cString::sprintf("H.264: %d x %d%c %.2f fps %d Bit", frameWidth, frameHeight, progressive ? 'p':'i', framesPerSecond, bitDepth); -- dsyslog(s); -+ dsyslog("%s", *s); - dbgframes("\n%s", *s); - } - } -@@ -1908,7 +1908,7 @@ void cH265Parser::ParseSequenceParameterSet(void) - } - if (debug) { - cString s = cString::sprintf("H.265: %d x %d%c %.2f fps %d Bit", frameWidth, frameHeight, progressive ? 'p':'i', framesPerSecond, bitDepth); -- dsyslog(s); -+ dsyslog("%s", *s); - dbgframes("\n%s", *s); - } - } diff --git a/vdr-2.7.2-timers.patch b/vdr-2.7.2-timers.patch deleted file mode 100644 index 56669da..0000000 --- a/vdr-2.7.2-timers.patch +++ /dev/null @@ -1,44 +0,0 @@ ---- timers.c 2024/03/06 14:37:15 5.20 -+++ timers.c 2024/10/10 09:23:34 -@@ -726,10 +726,39 @@ - bool cTimer::Expired(void) const - { - if (IsSingleEvent() && !Recording()) { -+ time_t Now = time(NULL); - time_t ExpireTime = StopTimeEvent(); -- if (HasFlags(tfVps)) -+ if (HasFlags(tfVps)) { - ExpireTime += EXPIRELATENCY; -- return ExpireTime <= time(NULL); -+ if (ExpireTime <= Now) { -+ LOCK_SCHEDULES_READ; -+ const cSchedule *Schedule = event ? event->Schedule() : NULL; -+ const cEvent *FirstEvent = event; -+ if (Schedule) -+ FirstEvent = Schedule->Events()->Next(FirstEvent); -+ else if ((Schedule = Schedules->GetSchedule(Channel())) != NULL) { -+ FirstEvent = Schedule->Events()->First(); -+ if (FirstEvent) -+ dsyslog("timer %s had no event, got %s from channel/schedule", *ToDescr(), *FirstEvent->ToDescr()); -+ } -+ if (FirstEvent) { -+ if (Schedule) { -+ for (const cEvent *e = FirstEvent; e; e = Schedule->Events()->Next(e)) { -+ if (e->Vps() == startTime) { -+ ExpireTime = e->EndTime() + EXPIRELATENCY; -+ dsyslog("timer %s is waiting for next VPS event %s", *ToDescr(), *e->ToDescr()); -+ break; -+ } -+ } -+ } -+ } -+ else { -+ dsyslog("timer %s has no event, setting expiration to +24h", *ToDescr()); -+ ExpireTime += 3600 * 24; -+ } -+ } -+ } -+ return ExpireTime <= Now; - } - return false; - } diff --git a/vdr-2.7.3-remux-radio.patch b/vdr-2.7.3-remux-radio.patch deleted file mode 100644 index 094796e..0000000 --- a/vdr-2.7.3-remux-radio.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- remux.c 2024/10/08 08:46:38 5.14 -+++ remux.c 2024/10/13 13:34:32 -@@ -2274,6 +2274,7 @@ - } - else // audio - framesPerSecond = double(PTSTICKS) / Delta; // PTS of audio frames is always increasing -+ frameChecker->SetFrameDelta(Delta); - dbgframes("\nDelta = %d FPS = %5.2f FPPU = %d NF = %d TRO = %d\n", Delta, framesPerSecond, framesPerPayloadUnit, numPtsValues + 1, parser->IFrameTemporalReferenceOffset()); - synced = true; - parser->SetDebug(false); diff --git a/vdr-channel+epg.patch b/vdr-channel+epg.patch deleted file mode 100644 index 9315b1c..0000000 --- a/vdr-channel+epg.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff -up vdr-1.6.0/menu.c~ vdr-1.6.0/menu.c ---- vdr-1.6.0/menu.c~ 2008-03-16 13:15:28.000000000 +0200 -+++ vdr-1.6.0/menu.c 2011-02-15 00:39:42.267224859 +0200 -@@ -399,11 +399,20 @@ int cMenuChannelItem::Compare(const cLis - void cMenuChannelItem::Set(void) - { - cString buffer; -+ const cEvent *Event = NULL; - if (!channel->GroupSep()) { -+ cSchedulesLock SchedulesLock; -+ const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock); -+ const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID()); -+ if (Schedule) -+ Event = Schedule->GetPresentEvent(); -+ - if (sortMode == csmProvider) -- buffer = cString::sprintf("%d\t%s - %s", channel->Number(), channel->Provider(), channel->Name()); -+ buffer = cString::sprintf("%d\t%s - %s %c%s%c", channel->Number(), channel->Provider(), channel->Name(), -+ Event ? '(' : ' ', Event ? Event->Title() : "", Event ? ')' : ' '); - else -- buffer = cString::sprintf("%d\t%s", channel->Number(), channel->Name()); -+ buffer = cString::sprintf("%d\t%s %c%s%c", channel->Number(), channel->Name(), -+ Event ? '(' : ' ', Event ? Event->Title() : "", Event ? ')' : ' '); - } - else - buffer = cString::sprintf("---\t%s ----------------------------------------------------------------", channel->Name()); diff --git a/vdr-gcc11.patch b/vdr-gcc11.patch deleted file mode 100644 index 0ac2808..0000000 --- a/vdr-gcc11.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/recording.c b/recording.c -index e493b57..e50ef7d 100644 ---- a/recording.c -+++ b/recording.c -@@ -3025,7 +3025,15 @@ cUnbufferedFile *cFileName::SetOffset(int Number, off_t Offset) - } - // found a non existing file suffix - } -- if (Open() >= 0) { -+ /* This used to test Open() >= 0, but Open() returns a pointer -+ and we shouldn't be doing ordered comparisons of pointers -+ against constants. Furthermore, on some systems pointers -+ are unsigned meaning this test always succeeded. -+ -+ Finally, AFAICT Open() is always going to return NULL or a -+ valid pointer and can never return a negative value based on my -+ reading of these sources. */ -+ if (1) { - if (!record && Offset >= 0 && file && file->Seek(Offset, SEEK_SET) != Offset) { - LOG_ERROR_STR(fileName); - return NULL; diff --git a/vdr-gcc7-fix.patch b/vdr-gcc7-fix.patch deleted file mode 100644 index faaa88a..0000000 --- a/vdr-gcc7-fix.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/osdbase.c.orig 2017-02-15 15:55:34.555128665 +0100 -+++ b/osdbase.c 2017-02-15 15:56:30.898068614 +0100 -@@ -510,7 +510,7 @@ - const char *s = item->Text(); - i = 0; - item_nr = 0; -- if (s && (s = skipspace(s)) != '\0' && '0' <= s[i] && s[i] <= '9') { -+ if (s && (s = skipspace(s)) != NULL && '0' <= s[i] && s[i] <= '9') { - do { - item_nr = item_nr * 10 + (s[i] - '0'); - } diff --git a/vdr-timer-info-0.5-1.7.13.diff b/vdr-timer-info-0.5-1.7.13.diff deleted file mode 100644 index a0e8adb..0000000 --- a/vdr-timer-info-0.5-1.7.13.diff +++ /dev/null @@ -1,306 +0,0 @@ -#! /bin/sh /usr/share/dpatch/dpatch-run -## opt-41-x_timer-info.dpatch by Andreas Brugger , Thomas Günther -## http://toms-cafe.de/vdr/download/vdr-timer-info-0.5-1.7.13.diff -## -## All lines beginning with `## DP:' are a description of the patch. -## DP: Shows info, if it is possible to record an event in the timer-info of -## DP: vdr - see README.timer-info for details. - -@DPATCH@ -diff -Naurp vdr-1.7.13/README.timer-info vdr-1.7.13-timer-info-0.5/README.timer-info ---- vdr-1.7.13/README.timer-info 1970-01-01 00:00:00.000000000 +0000 -+++ vdr-1.7.13-timer-info-0.5/README.timer-info 2010-02-28 18:26:31.000000000 +0000 -@@ -0,0 +1,69 @@ -++------------------------------------------------------------------------------+ -+| Info about the timer-info-patch by Brougs78 | -+| brougs78@gmx.net / home.pages.at/brougs78 | -++------------------------------------------------------------------------------+ -+ -+ -+README timer-info: -+------------------ -+ -+Features: -+ - Shows info, if it is possible to record an event in the timer menu of vdr. -+ For calculations the free space incl. the deleted recordings is used, -+ considering an average consumtion of 25.75 MB/min (also used by vdr itself). -+ The first column in the timer-list shows: -+ ( + ) recording will be most probably possible (enough space) -+ (+/-) recording may be possible -+ ( - ) recording will most probably fail (to less space) -+ The calculations also consider repeating timers. -+ - It is possible to deactivate the patch in the OSD-menu of VDR. -+ -+ -+HISTORY timer-info: -+------------------- -+ -+25.11.2004: v0.1 -+ - Initial release -+ -+11.01.2005: v0.1b -+ - Bugfixes for vdr-1.3.18 -+ - In the menu the free recording-time no longer includes the space of the -+ deleted recordings, because this slowed the vdr down to much. -+ -+08.07.2005: v0.1c -+ - Made the patch configurable -+ -+29.01.2006: v0.2 - Thomas Günther -+ - Rewritten great parts for vdr-1.3.38+ -+ http://toms-cafe.de/vdr/download/vdr-timer-info-0.2-1.3.38+.diff -+ -+05.02.2006: v0.3 - Thomas Günther -+ - Fixed refresh of timer menu in cMenuTimers::OnOff -+ - Fixed check of repeating timers -+ - Syslog debug messages can be enabled with Define DEBUG_TIMER_INFO -+ http://toms-cafe.de/vdr/download/vdr-timer-info-0.3-1.3.38+.diff -+ -+03.03.2006: v0.4 - Thomas Günther -+ - Adapted to vdr-1.3.44 -+ - Removed setup parameter "Show timer-info" -+ http://toms-cafe.de/vdr/download/vdr-timer-info-0.4-1.3.44.diff -+ -+26.03.2006: - Tobias Grimm -+ - Adapted to vdr-1.3.45 -+ http://toms-cafe.de/vdr/download/vdr-timer-info-0.4-1.3.45.diff -+ -+14.01.2008: - Thomas Günther -+ - Adapted to vdr-1.5.13 -+ http://toms-cafe.de/vdr/download/vdr-timer-info-0.4-1.5.13.diff -+ -+17.02.2008: - Tobias Grimm -+ - Adapted to vdr-1.5.15 -+ http://toms-cafe.de/vdr/download/vdr-timer-info-0.4-1.5.15.diff -+ -+12.04.2008: v0.5 - Thomas Günther -+ - Fixed display of +/- sign with UTF-8 -+ http://toms-cafe.de/vdr/download/vdr-timer-info-0.5-1.5.15.diff -+ -+28.02.2010: - Thomas Günther -+ - Adapted to vdr-1.7.13 -+ http://toms-cafe.de/vdr/download/vdr-timer-info-0.5-1.7.13.diff -diff -Naurp vdr-1.7.13/menu.c vdr-1.7.13-timer-info-0.5/menu.c ---- vdr-1.7.13/menu.c 2010-02-21 14:09:19.000000000 +0000 -+++ vdr-1.7.13-timer-info-0.5/menu.c 2010-02-28 18:24:26.000000000 +0000 -@@ -1010,8 +1010,10 @@ eOSState cMenuEditTimer::ProcessKey(eKey - class cMenuTimerItem : public cOsdItem { - private: - cTimer *timer; -+ char diskStatus; - public: - cMenuTimerItem(cTimer *Timer); -+ void SetDiskStatus(char DiskStatus); - virtual int Compare(const cListObject &ListObject) const; - virtual void Set(void); - cTimer *Timer(void) { return timer; } -@@ -1020,6 +1022,7 @@ public: - cMenuTimerItem::cMenuTimerItem(cTimer *Timer) - { - timer = Timer; -+ diskStatus = ' '; - Set(); - } - -@@ -1050,7 +1053,10 @@ void cMenuTimerItem::Set(void) - File++; - else - File = timer->File(); -- SetText(cString::sprintf("%c\t%d\t%s%s%s\t%02d:%02d\t%02d:%02d\t%s", -+ cCharSetConv csc("ISO-8859-1", cCharSetConv::SystemCharacterTable()); -+ char diskStatusString[2] = { diskStatus, 0 }; -+ SetText(cString::sprintf("%s%c\t%d\t%s%s%s\t%02d:%02d\t%02d:%02d\t%s", -+ csc.Convert(diskStatusString), - !(timer->HasFlags(tfActive)) ? ' ' : timer->FirstDay() ? '!' : timer->Recording() ? '#' : '>', - timer->Channel()->Number(), - *name, -@@ -1063,6 +1069,57 @@ void cMenuTimerItem::Set(void) - File)); - } - -+void cMenuTimerItem::SetDiskStatus(char DiskStatus) -+{ -+ diskStatus = DiskStatus; -+ Set(); -+} -+ -+// --- cTimerEntry ----------------------------------------------------------- -+ -+class cTimerEntry : public cListObject { -+private: -+ cMenuTimerItem *item; -+ const cTimer *timer; -+ time_t start; -+public: -+ cTimerEntry(cMenuTimerItem *item) : item(item), timer(item->Timer()), start(timer->StartTime()) {} -+ cTimerEntry(const cTimer *timer, time_t start) : item(NULL), timer(timer), start(start) {} -+ virtual int Compare(const cListObject &ListObject) const; -+ bool active(void) const { return timer->HasFlags(tfActive); } -+ time_t startTime(void) const { return start; } -+ int priority(void) const { return timer->Priority(); } -+ int duration(void) const; -+ bool repTimer(void) const { return !timer->IsSingleEvent(); } -+ bool isDummy(void) const { return item == NULL; } -+ const cTimer *Timer(void) const { return timer; } -+ void SetDiskStatus(char DiskStatus); -+ }; -+ -+int cTimerEntry::Compare(const cListObject &ListObject) const -+{ -+ cTimerEntry *entry = (cTimerEntry *)&ListObject; -+ int r = startTime() - entry->startTime(); -+ if (r == 0) -+ r = entry->priority() - priority(); -+ return r; -+} -+ -+int cTimerEntry::duration(void) const -+{ -+ int dur = (timer->Stop() / 100 * 60 + timer->Stop() % 100) - -+ (timer->Start() / 100 * 60 + timer->Start() % 100); -+ if (dur < 0) -+ dur += 24 * 60; -+ return dur; -+} -+ -+void cTimerEntry::SetDiskStatus(char DiskStatus) -+{ -+ if (item) -+ item->SetDiskStatus(DiskStatus); -+} -+ - // --- cMenuTimers ----------------------------------------------------------- - - class cMenuTimers : public cOsdMenu { -@@ -1075,14 +1132,17 @@ private: - eOSState Info(void); - cTimer *CurrentTimer(void); - void SetHelpKeys(void); -+ void ActualiseDiskStatus(void); -+ bool actualiseDiskStatus; - public: - cMenuTimers(void); - virtual ~cMenuTimers(); -+ virtual void Display(void); - virtual eOSState ProcessKey(eKeys Key); - }; - - cMenuTimers::cMenuTimers(void) --:cOsdMenu(tr("Timers"), 2, CHNUMWIDTH, 10, 6, 6) -+:cOsdMenu(tr("Timers"), 3, CHNUMWIDTH, 10, 6, 6) - { - helpKeys = -1; - for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) { -@@ -1093,6 +1153,7 @@ cMenuTimers::cMenuTimers(void) - SetCurrent(First()); - SetHelpKeys(); - Timers.IncBeingEdited(); -+ actualiseDiskStatus = true; - } - - cMenuTimers::~cMenuTimers() -@@ -1131,7 +1192,7 @@ eOSState cMenuTimers::OnOff(void) - timer->OnOff(); - timer->SetEventFromSchedule(); - RefreshCurrent(); -- DisplayCurrent(true); -+ Display(); - if (timer->FirstDay()) - isyslog("timer %s first day set to %s", *timer->ToDescr(), *timer->PrintFirstDay()); - else -@@ -1190,6 +1251,67 @@ eOSState cMenuTimers::Info(void) - return osContinue; - } - -+void cMenuTimers::ActualiseDiskStatus(void) -+{ -+ if (!actualiseDiskStatus || !Count()) -+ return; -+ -+ // compute free disk space -+ int freeMB, freeMinutes, runshortMinutes; -+ VideoDiskSpace(&freeMB); -+ freeMinutes = int(double(freeMB) * 1.1 / MB_PER_MINUTE); // overestimate by 10 percent -+ runshortMinutes = freeMinutes / 5; // 20 Percent -+ -+ // fill entries list -+ cTimerEntry *entry; -+ cList entries; -+ for (cOsdItem *item = First(); item; item = Next(item)) -+ entries.Add(new cTimerEntry((cMenuTimerItem *)item)); -+ -+ // search last start time -+ time_t last = 0; -+ for (entry = entries.First(); entry; entry = entries.Next(entry)) -+ last = max(entry->startTime(), last); -+ -+ // add entries for repeating timers -+ for (entry = entries.First(); entry; entry = entries.Next(entry)) -+ if (entry->repTimer() && !entry->isDummy()) -+ for (time_t start = cTimer::IncDay(entry->startTime(), 1); -+ start <= last; -+ start = cTimer::IncDay(start, 1)) -+ if (entry->Timer()->DayMatches(start)) -+ entries.Add(new cTimerEntry(entry->Timer(), start)); -+ -+ // set the disk-status -+ entries.Sort(); -+ for (entry = entries.First(); entry; entry = entries.Next(entry)) { -+ char status = ' '; -+ if (entry->active()) { -+ freeMinutes -= entry->duration(); -+ status = freeMinutes > runshortMinutes ? '+' : freeMinutes > 0 ? 177 /* +/- */ : '-'; -+ } -+ entry->SetDiskStatus(status); -+#ifdef DEBUG_TIMER_INFO -+ dsyslog("timer-info: %c | %d | %s | %s | %3d | %+5d -> %+5d", -+ status, -+ entry->startTime(), -+ entry->active() ? "aktiv " : "n.akt.", -+ entry->repTimer() ? entry->isDummy() ? " dummy " : "mehrmalig" : "einmalig ", -+ entry->duration(), -+ entry->active() ? freeMinutes + entry->duration() : freeMinutes, -+ freeMinutes); -+#endif -+ } -+ -+ actualiseDiskStatus = false; -+} -+ -+void cMenuTimers::Display(void) -+{ -+ ActualiseDiskStatus(); -+ cOsdMenu::Display(); -+} -+ - eOSState cMenuTimers::ProcessKey(eKeys Key) - { - int TimerNumber = HasSubMenu() ? Count() : -1; -@@ -1198,18 +1320,22 @@ eOSState cMenuTimers::ProcessKey(eKeys K - if (state == osUnknown) { - switch (Key) { - case kOk: return Edit(); -- case kRed: state = OnOff(); break; // must go through SetHelpKeys()! -+ case kRed: actualiseDiskStatus = true; -+ state = OnOff(); break; // must go through SetHelpKeys()! - case kGreen: return New(); -- case kYellow: state = Delete(); break; -+ case kYellow: actualiseDiskStatus = true; -+ state = Delete(); break; - case kInfo: - case kBlue: return Info(); - break; - default: break; - } - } -- if (TimerNumber >= 0 && !HasSubMenu() && Timers.Get(TimerNumber)) { -- // a newly created timer was confirmed with Ok -- Add(new cMenuTimerItem(Timers.Get(TimerNumber)), true); -+ if (TimerNumber >= 0 && !HasSubMenu()) { -+ if (Timers.Get(TimerNumber)) // a newly created timer was confirmed with Ok -+ Add(new cMenuTimerItem(Timers.Get(TimerNumber)), true); -+ Sort(); -+ actualiseDiskStatus = true; - Display(); - } - if (Key != kNone) diff --git a/vdr-timer-info-2.2.0.patch b/vdr-timer-info-2.2.0.patch deleted file mode 100644 index 5f9fe2e..0000000 --- a/vdr-timer-info-2.2.0.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/menu.c b/menu.c -index 14be0ed..9c6a0ff 100644 ---- a/menu.c -+++ b/menu.c -@@ -1377,8 +1377,8 @@ void cMenuTimers::ActualiseDiskStatus(void) - - // compute free disk space - int freeMB, freeMinutes, runshortMinutes; -- VideoDiskSpace(&freeMB); -- freeMinutes = int(double(freeMB) * 1.1 / MB_PER_MINUTE); // overestimate by 10 percent -+ cVideoDirectory::VideoDiskSpace(&freeMB); -+ freeMinutes = int(double(freeMB) * 1.1 / 25.75); // overestimate by 10 percent - runshortMinutes = freeMinutes / 5; // 20 Percent - - // fill entries list diff --git a/vdr.epgsearch-exttimeredit-0.0.2.diff b/vdr.epgsearch-exttimeredit-0.0.2.diff deleted file mode 100644 index c92ff8c..0000000 --- a/vdr.epgsearch-exttimeredit-0.0.2.diff +++ /dev/null @@ -1,110 +0,0 @@ ---- menu.c.orig 2009-04-11 14:47:08.000000000 +0200 -+++ menu.c 2009-04-17 13:53:05.000000000 +0200 -@@ -853,6 +853,7 @@ eOSState cMenuEditTimer::ProcessKey(eKey - class cMenuTimerItem : public cOsdItem { - private: - cTimer *timer; -+ void DoSet(void); - public: - cMenuTimerItem(cTimer *Timer); - virtual int Compare(const cListObject &ListObject) const; -@@ -863,7 +864,7 @@ public: - cMenuTimerItem::cMenuTimerItem(cTimer *Timer) - { - timer = Timer; -- Set(); -+ DoSet(); - } - - int cMenuTimerItem::Compare(const cListObject &ListObject) const -@@ -873,6 +874,18 @@ int cMenuTimerItem::Compare(const cListO - - void cMenuTimerItem::Set(void) - { -+ // check for deleted timer -+ for (cTimer *t = Timers.First(); ; t = Timers.Next(t)) { -+ if (t == timer) -+ break; // timer still there -+ if (t == NULL) -+ return; // no matching timer found -+ } -+ DoSet(); -+} -+ -+void cMenuTimerItem::DoSet(void) -+{ - cString day, name(""); - if (timer->WeekDays()) - day = timer->PrintDay(0, timer->WeekDays(), false); -@@ -906,8 +919,7 @@ void cMenuTimerItem::Set(void) - class cMenuTimers : public cOsdMenu { - private: - int helpKeys; -- eOSState Edit(void); -- eOSState New(void); -+ eOSState Edit(bool New = false); - eOSState Delete(void); - eOSState OnOff(void); - eOSState Info(void); -@@ -980,19 +992,30 @@ eOSState cMenuTimers::OnOff(void) - return osContinue; - } - --eOSState cMenuTimers::Edit(void) -+eOSState cMenuTimers::Edit(bool New) - { -- if (HasSubMenu() || Count() == 0) -+ if (HasSubMenu() || (Count() == 0 && !New)) - return osContinue; -- isyslog("editing timer %s", *CurrentTimer()->ToDescr()); -- return AddSubMenu(new cMenuEditTimer(CurrentTimer())); --} -+ if (!New) -+ isyslog("editing timer %s", *CurrentTimer()->ToDescr()); - --eOSState cMenuTimers::New(void) --{ -- if (HasSubMenu()) -- return osContinue; -- return AddSubMenu(new cMenuEditTimer(new cTimer, true)); -+ // Data structure for service "Epgsearch-exttimeredit-v1.0" -+ struct Epgsearch_exttimeredit_v1_0 -+ { -+ // in -+ cTimer* timer; // pointer to the timer to edit -+ bool bNew; // flag that indicates, if this is a new timer or an existing one -+ const cEvent* event; // pointer to the event corresponding to this timer (may be NULL) -+ // out -+ cOsdMenu* pTimerMenu; // pointer to the menu of results -+ } exttimeredit; -+ exttimeredit.timer = New ? (new cTimer) : CurrentTimer(); -+ exttimeredit.bNew = New; -+ exttimeredit.event = exttimeredit.timer->Event(); -+ if (cPluginManager::CallFirstService("Epgsearch-exttimeredit-v1.0", &exttimeredit)) -+ return AddSubMenu(exttimeredit.pTimerMenu); -+ -+ return AddSubMenu(new cMenuEditTimer(exttimeredit.timer, New)); - } - - eOSState cMenuTimers::Delete(void) -@@ -1038,7 +1061,7 @@ eOSState cMenuTimers::ProcessKey(eKeys K - switch (Key) { - case kOk: return Edit(); - case kRed: state = OnOff(); break; // must go through SetHelpKeys()! -- case kGreen: return New(); -+ case kGreen: return Edit(true); - case kYellow: state = Delete(); break; - case kInfo: - case kBlue: return Info(); -@@ -1051,6 +1074,11 @@ eOSState cMenuTimers::ProcessKey(eKeys K - Add(new cMenuTimerItem(Timers.Get(TimerNumber)), true); - Display(); - } -+ if (!HasSubMenu() && Timers.Count()