diff --git a/.gitignore b/.gitignore index b3aaae8..e5e9b86 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,7 @@ /*.gz /*.bz2 +/62efcc0b4a1f.zip +/2ea854ae8c7a.zip +/vdr-dvbsddevice-2.2.0.tgz +/vdr-rcu-2.2.0.tgz +/3473a7b939d7.zip 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/12_osdbase-maxitems.patch b/12_osdbase-maxitems.patch new file mode 100644 index 0000000..78ab64a --- /dev/null +++ b/12_osdbase-maxitems.patch @@ -0,0 +1,38 @@ +Description: Fixes problems with text2skin skin enigma. +Author: Andreas Brugger +Origin: http://vdrportal.de/board/thread.php?postid=343665#post343665 + +--- a/osdbase.c ++++ b/osdbase.c +@@ -345,6 +345,7 @@ + + void cOsdMenu::CursorUp(void) + { ++ displayMenuItems = displayMenu->MaxItems(); + int tmpCurrent = current; + int lastOnScreen = first + displayMenuItems - 1; + int last = Count() - 1; +@@ -383,6 +384,7 @@ + + void cOsdMenu::CursorDown(void) + { ++ displayMenuItems = displayMenu->MaxItems(); + int tmpCurrent = current; + int lastOnScreen = first + displayMenuItems - 1; + int last = Count() - 1; +@@ -423,6 +425,7 @@ + + void cOsdMenu::PageUp(void) + { ++ displayMenuItems = displayMenu->MaxItems(); + int oldCurrent = current; + int oldFirst = first; + current -= displayMenuItems; +@@ -457,6 +460,7 @@ + + void cOsdMenu::PageDown(void) + { ++ displayMenuItems = displayMenu->MaxItems(); + int oldCurrent = current; + int oldFirst = first; + current += displayMenuItems; diff --git a/MainMenuHooks-v1_0_4.diff.txt b/MainMenuHooks-v1_0_4.diff.txt new file mode 100644 index 0000000..f24df98 --- /dev/null +++ b/MainMenuHooks-v1_0_4.diff.txt @@ -0,0 +1,191 @@ +This is a "patch" for the Video Disk Recorder (VDR). + +* History +2025-02-26: Version 1.0.4 +Update für vdr-2.7.4 (Jörg Riechardt) + +2013-11-08: Version 1.0.3 +Update für vdr-2.1.2 (Jörg Riechardt) + +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. + + +diff -Nrup vdr-2.7.4/config.h vdr-2.7.4-test/config.h +--- vdr-2.7.4/config.h 2025-02-26 10:35:03.000000000 +0100 ++++ vdr-2.7.4-test/config.h 2025-02-26 14:46:28.768820964 +0100 +@@ -35,6 +35,10 @@ + // only when there are changes to the plugin API. This allows compiled + // plugins to work with newer versions of the core VDR as long as no + // interfaces have changed. APIVERSNUM begins with "300.." for backwards ++ ++// The MainMenuHook Patch's version number: ++#define MAINMENUHOOKSVERSION "1.0.1" ++#define MAINMENUHOOKSVERSNUM 10001 // Version * 10000 + Major * 100 + Minor + // compatibility and can be used in #if preprocessor statements to handle + // version dependent code. + +diff -Nrup vdr-2.7.4/menu.c vdr-2.7.4-test/menu.c +--- vdr-2.7.4/menu.c 2025-02-26 10:35:03.000000000 +0100 ++++ vdr-2.7.4-test/menu.c 2025-02-26 15:20:42.252563574 +0100 +@@ -4493,15 +4493,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) +@@ -4613,13 +4629,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?"))) { + if (cOsdItem *item = Get(Current())) { + cRecordControls::Stop(item->Text() + strlen(tr(STOP_RECORDING))); +@@ -4670,6 +4707,12 @@ eOSState cMenuMain::ProcessKey(eKeys Key + default: break; + } + } ++ if (menu) { ++ if (menu->IsMenu()) ++ return AddSubMenu((cOsdMenu *) menu); ++ pluginOsdObject = menu; ++ return osPlugin; ++ } + bool DoDisplay = Update(); + if (Key != kNone) { + if (I18nCurrentLanguage() != osdLanguage) { diff --git a/define_AUDIO_GET_PTS.patch b/define_AUDIO_GET_PTS.patch new file mode 100644 index 0000000..5160cea --- /dev/null +++ b/define_AUDIO_GET_PTS.patch @@ -0,0 +1,12 @@ +--- vdr-2.4.0/PLUGINS/src/dvbhddevice/dvbhdffdevice.h.orig 2018-10-10 11:56:49.181447499 +0200 ++++ vdr-2.4.0/PLUGINS/src/dvbhddevice/dvbhdffdevice.h 2018-10-10 11:57:49.263760610 +0200 +@@ -4,6 +4,9 @@ + * See the README file for copyright information and how to reach the author. + */ + ++#ifndef AUDIO_GET_PTS ++#define AUDIO_GET_PTS _IOR('o', 19, __u64) ++#endif + #ifndef __DVBHDFFDEVICE_H + #define __DVBHDFFDEVICE_H + diff --git a/sources b/sources index 8afd75d..2a16883 100644 --- a/sources +++ b/sources @@ -1,6 +1,7 @@ -3e9287f726df5a667054a15078235791 vdr_1.4.5-2.ds.diff.gz -8853f64c0fc3d41ffd3b4bfc6f0a14b7 vdr-2.2.0.tar.bz2 -77a858732829b95351a67dfe660b1c11 vdr-2.2.0-editrecording.patch.gz -f238e515be830ecc594a044bd8c8dbf6 vdr-2.2.0-menuselection.patch.gz -9ccbbf47c58ea6fe23b5510c36aec38e vdr-2.2.0-lcn-support-v2.patch.gz -bff4cfac7535d88b5e7a2825283c3f9e vdr_2.2.0-5.debian.tar.bz2 +SHA512 (vdr-2.7.7.tar.bz2) = 22c561aea6c2ae29f27d024249501c3c748cd77e9c182ed969a59f24b4b360b59cf807e1214665bbec7797b6ec11beeac0b2f02e8427f0c91cf9c29144bd5154 +SHA512 (vdr-rcu-2.2.0.tgz) = 56abebcfde3511c4dcf6f414915c7aa70a16b8e138e2d9364080828edc9b0da045acaadaaa4094d1315ddefdafa5f966aebcfacf979c068e077f1e32e29773b7 +SHA512 (vdr-dvbsddevice-2.2.0.tgz) = ac0b94b8b192208ad7e736d7c4f27cca6517134b17fc86a79cdd19453176d5f6076418bf679435899cd953053f3b54776342bcdab23a659e8331e9f2ed4ee364 +SHA512 (3473a7b939d7.zip) = fc405ac81cc1374de3a2d457f76972e605cf51c20c5e86f4fb683bb7fc78fde51690e65f463870c6881a65308722ccecd60d4a8957e3e2d43ecfd665f0e5aa8f +SHA512 (vdr_2.2.0-5.debian.tar.bz2) = 6ba924fee84673be2a2652a26bccde4dc07dd9c7bcc871868f44bdc2748136a8ac26feb026c5b5dd9b3831c641ef1e729052c1190a45cc805f3fa563c3a59798 +SHA512 (vdr_1.4.5-2.ds.diff.gz) = dc82ca24e830a4fc4bfed51b2d112301b9058f2d1fea93761a42df8715dbe3ba0e9e8621464c8a6fe2dd3bd62d33efaff911182d3489ef741096654b7a3eb326 +SHA512 (vdr-2.4.6-editrecording.patch.gz) = 0935fdbe6b557c8b03396ff31021b35758a040f297315f39bdf605961a8ad77897884b527e2655e36ff8241e06cd1b2592c3bd0be09e78434263e43e85368e86 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-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-1.7.41-paths.patch b/vdr-2.4.0-paths.patch similarity index 51% rename from vdr-1.7.41-paths.patch rename to vdr-2.4.0-paths.patch index 742c291..1ef982d 100644 --- a/vdr-1.7.41-paths.patch +++ b/vdr-2.4.0-paths.patch @@ -1,25 +1,6 @@ -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"; +--- vdr-2.4.0/newplugin.orig 2018-04-15 17:42:19.464011065 +0200 ++++ vdr-2.4.0/newplugin 2018-04-15 17:42:56.071975982 +0200 +@@ -24,7 +24,7 @@ $PLUGIN_DESCRIPTION = "Enter description for '$PLUGIN_NAME' plugin"; $PLUGIN_MAINENTRY = $PLUGIN_CLASS; @@ -28,10 +9,9 @@ diff -up vdr-1.7.41/newplugin~ vdr-1.7.41/newplugin $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 +--- vdr-2.4.0/vdr.1.orig 2018-04-15 17:44:29.594888585 +0200 ++++ vdr-2.4.0/vdr.1 2018-04-15 17:48:32.015340633 +0200 +@@ -56,7 +56,7 @@ .TP .BI \-c\ dir ,\ \-\-config= dir Read config files from directory \fIdir\fR @@ -40,7 +20,7 @@ diff -up vdr-1.7.41/vdr.1~ vdr-1.7.41/vdr.1 .TP .B \-d, \-\-daemon Run in daemon mode (implies \-\-no\-kbd). -@@ -130,7 +130,7 @@ If logging should be done to LOG_LOCAL\f +@@ -137,7 +137,7 @@ LOG_USER, add '.n' to LEVEL, as in 3.7 (n=0..7). .TP .BI \-L\ dir ,\ \-\-lib= dir @@ -49,7 +29,7 @@ diff -up vdr-1.7.41/vdr.1~ vdr-1.7.41/vdr.1 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 \-\ +@@ -231,7 +231,7 @@ .TP .BI \-v\ dir ,\ \-\-video= dir Use \fIdir\fR as video directory. @@ -58,10 +38,9 @@ diff -up vdr-1.7.41/vdr.1~ vdr-1.7.41/vdr.1 .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 +--- vdr-2.4.0/vdr.5.orig 2018-04-15 17:51:02.213282179 +0200 ++++ vdr-2.4.0/vdr.5 2018-04-15 17:52:51.799237923 +0200 +@@ -714,7 +714,7 @@ Each line contains one option in the format "Name = Value". See the MANUAL file for a description of the available options. .SS THEMES @@ -70,10 +49,9 @@ diff -up vdr-1.7.41/vdr.5~ vdr-1.7.41/vdr.5 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[]) +--- vdr-2.4.0/vdr.c.orig 2018-04-15 17:53:51.107197519 +0200 ++++ vdr-2.4.0/vdr.c 2018-04-15 17:54:44.512159912 +0200 +@@ -750,7 +750,7 @@ if (!ResourceDirectory) ResourceDirectory = DEFAULTRESDIR; cPlugin::SetResourceDirectory(ResourceDirectory); diff --git a/vdr-2.4.6-ClearObsoleteChannels2.diff b/vdr-2.4.6-ClearObsoleteChannels2.diff new file mode 100644 index 0000000..5251d87 --- /dev/null +++ b/vdr-2.4.6-ClearObsoleteChannels2.diff @@ -0,0 +1,58 @@ +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-07 10:05:06.503383738 +0100 +@@ -1145,3 +1145,23 @@ cString ChannelString(const cChannel *Ch + snprintf(buffer, sizeof(buffer), "%s", tr("*** Invalid Channel ***")); + return buffer; + } ++ ++// --- cChannel cont. -------------------------------------------------------- ++ ++bool cChannel::ClearObsoleteChannel(void) ++{ ++ bool ChannelsModified = false; ++ if (time(NULL) - Seen() <= CHANNELTIMEOBSOLETE && endswith(name, CHANNELMARKOBSOLETE)) { ++ int mlen = strlen(CHANNELMARKOBSOLETE); ++ int e = strlen(name) - mlen - 1; ++ name[e] = '\0'; ++ cString clrname = cString::sprintf("%s", name); ++ name[e] = ' '; ++ ++ int OldShowChannelNamesWithSource = Setup.ShowChannelNamesWithSource; ++ Setup.ShowChannelNamesWithSource = 0; ++ ChannelsModified |= SetName(clrname, shortName, provider + mlen + 1); ++ Setup.ShowChannelNamesWithSource = OldShowChannelNamesWithSource; ++ } ++ return ChannelsModified; ++} +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 2021-01-06 22:35:28.224118499 +0100 +@@ -202,6 +202,7 @@ public: + void SetRefChannel(cChannel *RefChannel); + bool SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *CompositionPageIds, uint16_t *AncillaryPageIds); + void SetSeen(void); ++ bool ClearObsoleteChannel(void); + void DelLinkChannel(cChannel *LinkChannel); + }; + +diff -Nurp vdr-2.4.6.orig/pat.c vdr-2.4.6/pat.c +--- vdr-2.4.6.orig/pat.c 2020-12-18 15:51:57.000000000 +0100 ++++ vdr-2.4.6/pat.c 2021-01-07 10:34:00.956778138 +0100 +@@ -489,6 +499,7 @@ void cPatFilter::Process(u_short Pid, u_ + SwitchToNextPmtPid(); + cChannel *Channel = Channels->GetByServiceID(Source(), Transponder(), pmt.getServiceId()); + if (Channel) { ++ Channel->SetSeen(); + SI::CaDescriptor *d; + cCaDescriptors *CaDescriptors = new cCaDescriptors(Channel->Source(), Channel->Transponder(), Channel->Sid(), Pid); + // Scan the common loop: +@@ -718,6 +729,8 @@ void cPatFilter::Process(u_short Pid, u_ + } + } + } ++ if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3) ++ ChannelsModified |= Channel->ClearObsoleteChannel(); + if (Setup.UpdateChannels >= 2) { + ChannelsModified |= Channel->SetPids(Vpid, Ppid, Vtype, Apids, Atypes, ALangs, Dpids, Dtypes, DLangs, Spids, SLangs, Tpid); + ChannelsModified |= Channel->SetCaIds(CaDescriptors->CaIds()); diff --git a/vdr-2.7.2-timers.patch b/vdr-2.7.2-timers.patch new file mode 100644 index 0000000..56669da --- /dev/null +++ b/vdr-2.7.2-timers.patch @@ -0,0 +1,44 @@ +--- 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-1.7.37-fedora-pkgconfig.patch b/vdr-2.7.4-fedora-pkgconfig.patch similarity index 63% rename from vdr-1.7.37-fedora-pkgconfig.patch rename to vdr-2.7.4-fedora-pkgconfig.patch index a80fd82..914eb08 100644 --- a/vdr-1.7.37-fedora-pkgconfig.patch +++ b/vdr-2.7.4-fedora-pkgconfig.patch @@ -1,7 +1,6 @@ -diff -up vdr-1.7.37/Makefile~ vdr-1.7.37/Makefile ---- vdr-1.7.37/Makefile~ 2013-02-14 21:57:22.306077727 +0200 -+++ vdr-1.7.37/Makefile 2013-02-14 22:05:04.016086224 +0200 -@@ -152,6 +152,12 @@ vdr.pc: +--- vdr-2.7.4/Makefile.orig 2025-02-26 14:07:24.323718942 +0100 ++++ vdr-2.7.4/Makefile 2025-02-26 14:08:33.583687374 +0100 +@@ -186,6 +186,12 @@ @echo "cflags=$(CFLAGS) $(CDEFINES) $(CINCLUDES) $(HDRDIR)" >> $@ @echo "cxxflags=$(CXXFLAGS) $(CDEFINES) $(CINCLUDES) $(HDRDIR)" >> $@ @echo "" >> $@ @@ -13,4 +12,4 @@ diff -up vdr-1.7.37/Makefile~ vdr-1.7.37/Makefile + @echo "" >> $@ @echo "Name: VDR" >> $@ @echo "Description: Video Disk Recorder" >> $@ - @echo "URL: http://www.tvdr.de/" >> $@ + @echo "URL: https://www.tvdr.de/" >> $@ 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-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()= 136-1 for the audio, cdrom, dialout, and video groups Requires: udev >= 136-1 # sudo for the shutdown script, >= 1.7.2p2-3 for sudoers.d functionality @@ -102,8 +98,6 @@ Requires: sudo >= 1.7.2p2-3 # util-linux >= 2.15 for "rtcwake -m no" timer driven wakeups Requires: util-linux >= 2.15 Requires: vdrsymbol-fonts -# shadow-utils >= 4.1.1 for useradd -N -Requires(pre): shadow-utils >= 2:4.1.1 # systemd >= 189 for RestartPreventExitStatus= Requires(post,preun,postun): systemd >= 189 Provides: vdr(abi)%{?_isa} = %{apiver} @@ -118,7 +112,7 @@ is required to run VDR. %package devel Summary: Development files for VDR -Requires: gettext +Requires: gettext-runtime Provides: vdr-devel(api) = %{apiver} %description devel @@ -170,18 +164,27 @@ window, using only plain text output. %prep %setup -q -a 18 -%patch0 -p1 -%patch1 -p1 +# dvbhddevice +unzip -o %{SOURCE30} -d $RPM_BUILD_DIR/vdr-%{version}/PLUGINS/src +mv $RPM_BUILD_DIR/vdr-%{version}/PLUGINS/src/powARman-dvbhddevice-3473a7b939d7 $RPM_BUILD_DIR/vdr-%{version}/PLUGINS/src/dvbhddevice +cd PLUGINS/src +%patch 0 -p3 +cd ../.. +# dvbsddevice +tar -xzf %{SOURCE31} -C $RPM_BUILD_DIR/vdr-%{version}/PLUGINS/src +mv $RPM_BUILD_DIR/vdr-%{version}/PLUGINS/src/dvbsddevice-2.2.0 $RPM_BUILD_DIR/vdr-%{version}/PLUGINS/src/dvbsddevice +# rcu +tar -xzf %{SOURCE32} -C $RPM_BUILD_DIR/vdr-%{version}/PLUGINS/src +mv $RPM_BUILD_DIR/vdr-%{version}/PLUGINS/src/rcu-2.2.0 $RPM_BUILD_DIR/vdr-%{version}/PLUGINS/src/rcu + +%patch 1 -p1 # sort_options would be nice, but it conflicts with channel+epg which is nicer #patch -F 0 -i debian/patches/02_sort_options.dpatch # TODO: does not apply since 1.7.24 #patch -F 0 -i debian/patches/06_recording_scan_speedup.dpatch patch -F 2 -i debian/patches/07_blockify_define.dpatch -# TODO: does not apply -#patch -F 0 -i debian/patches/10_livelock.dpatch -patch -F 0 -i debian/patches/12_osdbase-maxitems.patch -%patch2 -p1 -%patch3 -p1 +%patch 2 -p1 +%patch 3 -p1 sed \ -e 's|__CACHEDIR__|%{cachedir}|' \ -e 's|__CONFIGDIR__|%{configdir}|' \ @@ -189,27 +192,16 @@ sed \ -e 's|__VARDIR__|%{vardir}|' \ -e 's|__VIDEODIR__|%{videodir}|' \ %{PATCH4} | %{__patch} -p1 -%patch5 -p1 -F 2 -# TODO: does not apply -#patch6 -p0 -%patch7 -p1 -%patch8 -p1 -#TODO: patch9 -p1 -F 2 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -# TODO: does not apply -#patch13 -p1 -%patch14 -p1 -%patch15 -p1 -# TODO: build failure -#patch17 -p0 -F 3 -%patch18 -p1 -%patch19 -p1 -%patch20 -p1 -%patch21 -p1 +%patch 5 -p1 +%patch 11 -p1 +%patch 15 -p1 +%patch 99 -p1 -for f in CONTRIBUTORS HISTORY UPDATE-1.4.0 README.timer-info \ +# Patch APIVERSION TO 2.4.8 to match VDRVERSION +# sed -i 's/2\.4\.3/2.4.8/' config.h +# sed -i 's/20406/20407/' config.h + +for f in CONTRIBUTORS HISTORY UPDATE-1.4.0 \ PLUGINS/src/dvbhddevice/HISTORY; do iconv -f iso-8859-1 -t utf-8 -o $f.utf8 $f && mv $f.utf8 $f done @@ -240,9 +232,15 @@ for g in COLLABORATION INCLUDE INCLUDED_BY ; do sed -i -e 's/^\(\s*'$g'_GRAPH\s*=\s*\).*/\1NO/' Doxyfile done +# Create a sysusers.d config file +cat >vdr.sysusers.conf < Make.config CC = %{__cc} CXX = %{__cxx} @@ -266,6 +264,7 @@ LIBDIR = \$(PLUGINLIBDIR) PLGCFG = \$(LIBDIR)/plugins.mk LIRC_DEVICE = %{_localstatedir}/run/lirc/lircd +# New Bug 1873027 LIRC_DEVICE = /run/lirc/lircd VDR_USER = \$(shell pkg-config vdr --variable=user) SDNOTIFY = 1 EOF @@ -299,11 +298,10 @@ done %if %{with docs} %make_build srcdoc -%endif # docs +%endif %install - # Not using the install-pc target to preserve our already good vdr.pc install -Dpm 644 vdr.pc $RPM_BUILD_ROOT%{_libdir}/pkgconfig/vdr.pc @@ -313,7 +311,12 @@ make install-bin install-dirs install-conf install-doc install-i18n \ install -pm 755 epg2html $RPM_BUILD_ROOT%{_bindir} install -dm 755 $RPM_BUILD_ROOT%{_sbindir} -mv $RPM_BUILD_ROOT%{_bindir}/vdr $RPM_BUILD_ROOT%{_sbindir} +#mv $RPM_BUILD_ROOT%{_bindir}/vdr $RPM_BUILD_ROOT%{_sbindir} + +# Avoid mv error by checking if source and destination are the same +if [ "$RPM_BUILD_ROOT%{_bindir}/vdr" != "$RPM_BUILD_ROOT%{_sbindir}/vdr" ]; then + mv $RPM_BUILD_ROOT%{_bindir}/vdr $RPM_BUILD_ROOT%{_sbindir} +fi install -dm 755 $RPM_BUILD_ROOT%{configdir}/plugins @@ -414,6 +417,7 @@ echo "d %{rundir} 0755 %{vdr_user} root -" \ echo "%{_prefix}/lib/tmpfiles.d/%{name}.conf" \ >> %{name}.lang + # plugins %make_install -C PLUGINS/src/dvbhddevice @@ -434,6 +438,8 @@ install -pm 644 %{SOURCE11} \ $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/vdr-plugins.d/skincurses.conf %find_lang %{name}-skincurses +install -m0644 -D vdr.sysusers.conf %{buildroot}%{_sysusersdir}/vdr.conf + %check export PKG_CONFIG_PATH=$RPM_BUILD_ROOT%{_libdir}/pkgconfig @@ -442,14 +448,9 @@ if [ "$(pkg-config vdr --variable=apiversion)" != "%{apiver}" ] ; then fi -%pre -# dialout for serial port remote controllers -getent passwd %{vdr_user} >/dev/null || \ -useradd -r -g %{vdr_group} -d %{vardir} -s /sbin/nologin -M -N \ - -G audio,cdrom,dialout -c "Video Disk Recorder" %{vdr_user} || : - %post %systemd_post %{name}.service +systemctl daemon-reload %preun %systemd_preun %{name}.service @@ -498,13 +499,14 @@ useradd -r -g %{vdr_group} -d %{vardir} -s /sbin/nologin -M -N \ %dir %{vardir}/ %dir %{vardir}/themes/ %dir %{cachedir}/ +%{_sysusersdir}/vdr.conf %files devel -f %{name}-devel.files %{!?_with_docs:%dir %{_pkgdocdir}} %license COPYING %if ! %{with docs} %{_pkgdocdir}/PLUGINS.html -%endif # with docs +%endif %{_bindir}/vdr-config %{_bindir}/vdr-newplugin %{_includedir}/libsi/ @@ -550,9 +552,238 @@ useradd -r -g %{vdr_group} -d %{vardir} -s /sbin/nologin -M -N \ %changelog +* Fri Jul 25 2025 Martin Gansser - 2.7.7-1 +- Update to 2.7.7 + +* Fri Jul 25 2025 Fedora Release Engineering - 2.7.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + +* Sat Jun 21 2025 Martin Gansser - 2.7.6-1 +- Update to 2.7.6 + +* Tue May 27 2025 Martin Gansser - 2.7.5-1 +- Update to 2.7.5 +- Add vdr-2.7.5-override-keyword.patch + +* Sun May 11 2025 Peter Bieringer - 2.7.4-3 +- Re-add MainMenuHooks patch for 2.7.x + +* Thu Apr 24 2025 Zbigniew JÄ™drzejewski-Szmek - 2.7.4-2 +- Add sysusers.d config file to allow rpm to create users/groups automatically + +* Wed Feb 26 2025 Martin Gansser - 2.7.4-1 +- Update to 2.7.4 +- Add vdr-2.7.4-fedora-pkgconfig.patch + +* Fri Jan 24 2025 Martin Gansser - 2.7.3-3 +- Fix FTBFS #2341505 + +* Sun Jan 19 2025 Fedora Release Engineering - 2.7.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild + +* Mon Oct 14 2024 Martin Gansser - 2.7.3-1 +- Update to 2.7.3 +- Use recent dvbhddevice Source file 3473a7b939d7.zip +- Add %%{name}-2.7.3-remux-radio.patch + +* Sat Jul 20 2024 Fedora Release Engineering - 2.6.9-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + +* Mon Jul 15 2024 Martin Gansser - 2.6.9-1 +- Update to 2.6.9 + +* Sun Jul 14 2024 Martin Gansser - 2.6.8-2 +- Add vdr-2.6.8-fix-timeout-open-frontend.diff.txt +- Add vdr-2.6.8-fix-pause-epg-scan.diff.txt + +* Tue Jul 09 2024 Martin Gansser - 2.6.8-1 +- Update to 2.6.8 +- Add strreplace.patch + +* Tue Apr 02 2024 Martin Gansser - 2.6.7-1 +- Update to 2.6.7 + +* Fri Jan 26 2024 Martin Gansser - 2.6.6-1 +- Update to 2.6.6 + +* Wed Jan 03 2024 Martin Gansser - 2.6.5-1 +- Update to 2.6.5 +- vdr-devel does not require any translation management tools (BZ#2119032) + use RR gettext-runtime + +* Sat Jul 22 2023 Fedora Release Engineering - 2.6.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Mon Feb 20 2023 Martin Gansser - 2.6.4-1 +- Update to 2.6.4 + +* Fri Feb 10 2023 Fedora Release Engineering - 2.6.3-3 +- Rebuilt for rawhide + +* Sat Jan 21 2023 Fedora Release Engineering - 2.6.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Wed Dec 14 2022 Martin Gansser - 2.6.3-1 +- Update to 2.6.3 +- Dropped vdr-2.6.2-remux.patch +- Dropped vdr-2.6.2-index-file-regeneration-failed.patch + +* Thu Dec 01 2022 Martin Gansser - 2.6.2-2 +- Add vdr-2.6.2-index-file-regeneration-failed.patch + +* Wed Nov 30 2022 Martin Gansser - 2.6.2-1 +- Update to 2.6.2 +- Add vdr-2.6.2-remux.patch + +* Sat Jul 23 2022 Fedora Release Engineering - 2.6.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Thu Feb 03 2022 Martin Gansser - 2.6.1-1 +- Update to 2.6.1 + +* Sat Jan 29 2022 Martin Gansser - 2.6.0-4 +- Add vdr-2.6.0-fix-dvbplayer.diff +- Add %%undefine _package_note_flags + +* Sat Jan 22 2022 Fedora Release Engineering - 2.6.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Mon Jan 03 2022 Martin Gansser - 2.6.0-2 +- Reenable mainmenuhooks patch opt-42-x_MainMenuHooks-v1.0.3.patch +- Add vdr-2.6.0-eit.patch to fix epg handling transaction logic + +* Wed Dec 29 2021 Martin Gansser - 2.6.0-1 +- Update to 2.6.0 + +* Wed Dec 29 2021 Martin Gansser - 2.4.8-1 +- Update to 2.4.8 + +* Thu Oct 21 2021 Martin Gansser - 2.4.7-5 +- Delete missing kernel header files #Source33 because they are + available again in kernel-headers-5.14.0-300 package + +* Tue Aug 03 2021 Martin Gansser - 2.4.7-4 +- Add missing kernel-header files audio.h osd.h and video.h via #Source33 +- Add missing-kernel-headers.patch fixes (BZ#1989125) (BZ#1988085) + +* Tue Jul 27 2021 Fedora Release Engineering - 2.4.7-3 +- Second attempt - Rebuilt for + https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Sat Jun 12 2021 Martin Gansser - 2.4.7-2 +- Add vdr-2.4.7_gcc11.patch + +* Fri Apr 23 2021 Martin Gansser - 2.4.7-1 +- Update to 2.4.7 + +* Tue Feb 09 2021 Martin Gansser - 2.4.6-7 +- Add systemd watchdog support in to unit file vdr.service +- Add systemctl daemon-reload, because after every update of vdr, + it claims about missing systemd daemon-reload + +* Wed Jan 27 2021 Fedora Release Engineering - 2.4.6-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Fri Jan 22 2021 Martin Gansser - 2.4.6-5 +- Add modified vdr-2.4.4-RecordingInfo.patch for extrecmenung plugin + +* Sat Jan 16 2021 Martin Gansser - 2.4.6-4 +- Add vdr-2.4.4-RecordingInfo.patch for extrecmenung plugin +- Add mcli to sysconfig's VDR_PLUGIN_ORDER +- Add extrecmenung to sysconfig's VDR_PLUGIN_ORDER + +* Thu Jan 07 2021 Martin Gansser - 2.4.6-3 +- Add modified vdr-2.4.6-ClearObsoleteChannels2.diff + +* Sun Jan 03 2021 Martin Gansser - 2.4.6-2 +- Add vdr-2.4.6-ClearObsoleteChannels.diff + +* Mon Dec 28 2020 Martin Gansser - 2.4.6-1 +- Update to 2.4.6 +- Re-add vdr-2.4.6-editrecording.patch.gz +- Drop vdr-2.4.1-mark-obsolete-NidTid.patch +- set execution permission Doxyfile.filter +- Force C++14 as this code is not C++17 ready, needed for gcc11 + +* Wed Aug 26 2020 Martin Gansser - 2.4.4-1 +- Update to 2.4.4 +- Add vdr-2.4.1-mark-obsolete-NidTid.patch +- Dropped vdr-2.4.1-skincurses-log-errors.patch +- Dropped vdr-2.4.1-glibc231.patch +- Dropped vdr-2.4.1-editrecording.patch.gz +- Dropped vdr-2.4.1-lcn-support-v2.patch.gz + +* Fri Aug 14 2020 Martin Gansser - 2.4.1-8 +- Rebuilt for rawhide + +* Wed Jul 29 2020 Fedora Release Engineering - 2.4.1-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Sat Jun 27 2020 Martin Gansser - 2.4.1-6 +- Rebuilt for rawhide + +* Fri Jan 31 2020 Fedora Release Engineering - 2.4.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Sun Dec 15 2019 Martin Gansser - 2.4.1-4 +- Modify %%{name}-2.4.1-glibc231.patch + +* Sat Dec 14 2019 Martin Gansser - 2.4.1-3 +- Add %%{name}-2.4.1-glibc231.patch + +* Sat Jul 27 2019 Fedora Release Engineering - 2.4.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Mon Jun 17 2019 Martin Gansser - 2.4.1-1 +- Dropped Patch5 vdr-2.4.0-01-fix-svdrp-modt-recflag.diff +- Ccustomized Patch6 vdr-2.4.1-skincurses-log-errors.patch +- Add vdr-2.4.0-lcn-support-v2.patch.gz +- Add vdr-2.4.1-editrecording.patch.gz +- Fix systemd-tmpfiles migration warning, rundir from %%{_var}/run/vdr to /run/vdr + +* Sun Feb 03 2019 Fedora Release Engineering - 2.4.0-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Tue Nov 27 2018 Igor Gnatenko - 2.4.0-5 +- Rebuild for tinyxml2 7.x + +* Sun Oct 28 2018 Martin Gansser - 2.4.0-4 +- Re-add dvbsddevice Plugin +- Re-add rcu Plugin + +* Fri Sep 28 2018 Martin Gansser - 2.4.0-3 +- Add BR gcc +- Add BR gcc-c++ +- Update to dvbhddevice-2ea854ae8c7a +- Add define_AUDIO_GET_PTS.patch + +* Sat Jul 14 2018 Fedora Release Engineering - 2.4.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Mon Apr 16 2018 Martin Gansser - 2.4.0-1 +- Dropped dvbsddevice and rcu plugins +- SPEC File cleanup +- Dropped patch9 vdr-1.7.29-hlcutter-0.2.3.diff +- Dropped patch14 0001-Fix-build-with-systemd-230.patch +- Dropped patch19 vdr-2.2.0-menuselection.patch +- Dropped Patch20 %%{name}-2.3.2-unsignedtosigned.diff +- Dropped Patch21 %%{name}-gcc7-fix.patch +- Add %%{name}-2.4.0-01-fix-svdrp-modt-recflag.diff +- Add skincurses-log-errors.patch +- Add 12_osdbase-maxitems.patch + +* Fri Feb 09 2018 Igor Gnatenko - 2.2.0-14 +- Escape macros in %%changelog + +* Thu Aug 03 2017 Fedora Release Engineering - 2.2.0-13 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 2.2.0-12 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + * Thu Mar 02 2017 Martin Gansser - 2.2.0-11 -- Add %{name}-2.3.2-unsignedtosigned.diff -- Add %{name}-gcc7-fix.patch +- Add %%{name}-2.3.2-unsignedtosigned.diff +- Add %%{name}-gcc7-fix.patch * Fri Jun 17 2016 Ville Skyttä - 2.2.0-10 - Patch to fix build with systemd >= 230 (#1347724) diff --git a/vdr.sysconfig b/vdr.sysconfig index 137a235..0352405 100644 --- a/vdr.sysconfig +++ b/vdr.sysconfig @@ -18,6 +18,8 @@ VDR_OPTIONS=(--lirc --vfat --shutdown=vdr-shutdown.sh) # present when needed by other plugins at startup/shutdown. # VDR_PLUGIN_ORDER=" +mcli +extrecmenung dxr3 softdevice softhddevice @@ -52,7 +54,7 @@ burn # PATH where to find the internally used executables. # -PATH="/usr/lib/vdr/bin:$PATH" +PATH="/usr/lib64/vdr/bin:$PATH" # How many minutes before a recording should the VDR box wake up? # Some CI/CAM combinations can take quite a long time to initialize, so