Compare commits

..

No commits in common. "rawhide" and "f28" have entirely different histories.

26 changed files with 3409 additions and 676 deletions

5
.gitignore vendored
View file

@ -1,7 +1,2 @@
/*.gz
/*.bz2
/62efcc0b4a1f.zip
/2ea854ae8c7a.zip
/vdr-dvbsddevice-2.2.0.tgz
/vdr-rcu-2.2.0.tgz
/3473a7b939d7.zip

View file

@ -0,0 +1,29 @@
From 0376d2e4adc38528c0cbdde759a56700bee95872 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ville=20Skytt=C3=A4?= <ville.skytta@iki.fi>
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

View file

@ -1,38 +0,0 @@
Description: Fixes problems with text2skin skin enigma.
Author: Andreas Brugger <brougs78@gmx.net>
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;

View file

@ -1,191 +0,0 @@
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 <vdr at e-tobi dot net>
Martin Prochnow <nordlicht at martins-kabuff dot de>
Frank Schmirler <vdrdev at schmirler dot de>
Christian Wieninger <cwieninger at gmx dot de>
* 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) {

View file

@ -1,12 +0,0 @@
--- 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

13
sources
View file

@ -1,7 +1,6 @@
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
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

View file

@ -0,0 +1,106 @@
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;

114
vdr-1.5.18-syncearly.patch Normal file
View file

@ -0,0 +1,114 @@
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()

107
vdr-1.7.21-timercmd.patch Normal file
View file

@ -0,0 +1,107 @@
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(&parameter, "%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);

View file

@ -0,0 +1,612 @@
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);

View file

@ -1,6 +1,7 @@
--- 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 @@
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:
@echo "cflags=$(CFLAGS) $(CDEFINES) $(CINCLUDES) $(HDRDIR)" >> $@
@echo "cxxflags=$(CXXFLAGS) $(CDEFINES) $(CINCLUDES) $(HDRDIR)" >> $@
@echo "" >> $@
@ -12,4 +13,4 @@
+ @echo "" >> $@
@echo "Name: VDR" >> $@
@echo "Description: Video Disk Recorder" >> $@
@echo "URL: https://www.tvdr.de/" >> $@
@echo "URL: http://www.tvdr.de/" >> $@

View file

@ -1,6 +1,25 @@
--- 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 @@
diff -up vdr-1.7.41/epg2html~ vdr-1.7.41/epg2html
--- vdr-1.7.41/epg2html~ 2013-03-04 15:02:20.000000000 +0200
+++ vdr-1.7.41/epg2html 2013-03-16 19:08:17.467701640 +0200
@@ -2,12 +2,12 @@
# A simple EPG to HTML converter
#
-# Converts the EPG data written by 'vdr' into the file /video/epg.data
+# Converts the EPG data written by 'vdr' into the file __CACHEDIR__/epg.data
# into a simple HTML programme listing, consisting of one file per channel
# plus an 'index.htm' file. All output files are written into the current
# directory.
#
-# Usage: epg2html < /video/epg.data
+# Usage: epg2html < __CACHEDIR__/epg.data
#
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
diff -up vdr-1.7.41/newplugin~ vdr-1.7.41/newplugin
--- vdr-1.7.41/newplugin~ 2013-01-12 15:46:00.000000000 +0200
+++ vdr-1.7.41/newplugin 2013-03-16 19:08:18.140713300 +0200
@@ -24,7 +24,7 @@ $PLUGIN_VERSION = "0.0.1";
$PLUGIN_DESCRIPTION = "Enter description for '$PLUGIN_NAME' plugin";
$PLUGIN_MAINENTRY = $PLUGIN_CLASS;
@ -9,9 +28,10 @@
$README = qq
{This is a "plugin" for the Video Disk Recorder (VDR).
--- 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 @@
diff -up vdr-1.7.41/vdr.1~ vdr-1.7.41/vdr.1
--- vdr-1.7.41/vdr.1~ 2013-03-15 12:44:54.000000000 +0200
+++ vdr-1.7.41/vdr.1 2013-03-16 19:08:16.621686914 +0200
@@ -51,7 +51,7 @@ Save cache files in \fIdir\fR
.TP
.BI \-c\ dir ,\ \-\-config= dir
Read config files from directory \fIdir\fR
@ -20,7 +40,7 @@
.TP
.B \-d, \-\-daemon
Run in daemon mode (implies \-\-no\-kbd).
@@ -137,7 +137,7 @@
@@ -130,7 +130,7 @@ If logging should be done to LOG_LOCAL\f
LOG_USER, add '.n' to LEVEL, as in 3.7 (n=0..7).
.TP
.BI \-L\ dir ,\ \-\-lib= dir
@ -29,7 +49,7 @@
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
@@ -231,7 +231,7 @@
@@ -205,7 +205,7 @@ For backwards compatibility (same as \-\
.TP
.BI \-v\ dir ,\ \-\-video= dir
Use \fIdir\fR as video directory.
@ -38,9 +58,10 @@
.TP
.B \-V, \-\-version
Print version information and exit.
--- 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 @@
diff -up vdr-1.7.41/vdr.5~ vdr-1.7.41/vdr.5
--- vdr-1.7.41/vdr.5~ 2013-03-11 15:17:12.000000000 +0200
+++ vdr-1.7.41/vdr.5 2013-03-16 19:08:18.908726601 +0200
@@ -711,7 +711,7 @@ The file \fIsetup.conf\fR contains the b
Each line contains one option in the format "Name = Value".
See the MANUAL file for a description of the available options.
.SS THEMES
@ -49,9 +70,10 @@
color theme definitions for the various skins. In the actual file names \fI<skin>\fR
will be replaced by the name if the skin this theme belongs to, and \fI<theme>\fR
will be the name of this theme.
--- 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 @@
diff -up vdr-1.7.41/vdr.c~ vdr-1.7.41/vdr.c
--- vdr-1.7.41/vdr.c~ 2013-03-15 12:44:54.000000000 +0200
+++ vdr-1.7.41/vdr.c 2013-03-16 19:08:15.861673670 +0200
@@ -673,7 +673,7 @@ int main(int argc, char *argv[])
if (!ResourceDirectory)
ResourceDirectory = DEFAULTRESDIR;
cPlugin::SetResourceDirectory(ResourceDirectory);

View file

@ -0,0 +1,109 @@
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) {

621
vdr-2.1.5-naludump-0.1.diff Normal file
View file

@ -0,0 +1,621 @@
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<size; i++) {
+ History = (History << 8) | Payload[i];
+
+ PesOffset++;
+ NaluOffset++;
+
+ bool DropByte = false;
+
+ if (History >= 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<tempLength; i++)
+ tempBuffer[i] = tempBuffer[TS_SIZE-tempLength+i];
+ }
+ // Normalize TempBuffer fill
+ if (tempLength < TS_SIZE && length > 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

1016
vdr-2.2.0-ttxtsubs.patch Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,102 @@
--- 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)

View file

@ -1,58 +0,0 @@
diff -Nurp vdr-2.4.6.orig/channels.c vdr-2.4.6/channels.c
--- vdr-2.4.6.orig/channels.c 2020-04-11 11:22:05.000000000 +0200
+++ vdr-2.4.6/channels.c 2021-01-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());

View file

@ -1,44 +0,0 @@
--- timers.c 2024/03/06 14:37:15 5.20
+++ timers.c 2024/10/10 09:23:34
@@ -726,10 +726,39 @@
bool cTimer::Expired(void) const
{
if (IsSingleEvent() && !Recording()) {
+ time_t Now = time(NULL);
time_t ExpireTime = StopTimeEvent();
- if (HasFlags(tfVps))
+ if (HasFlags(tfVps)) {
ExpireTime += EXPIRELATENCY;
- return ExpireTime <= time(NULL);
+ if (ExpireTime <= Now) {
+ LOCK_SCHEDULES_READ;
+ const cSchedule *Schedule = event ? event->Schedule() : NULL;
+ const cEvent *FirstEvent = event;
+ if (Schedule)
+ FirstEvent = Schedule->Events()->Next(FirstEvent);
+ else if ((Schedule = Schedules->GetSchedule(Channel())) != NULL) {
+ FirstEvent = Schedule->Events()->First();
+ if (FirstEvent)
+ dsyslog("timer %s had no event, got %s from channel/schedule", *ToDescr(), *FirstEvent->ToDescr());
+ }
+ if (FirstEvent) {
+ if (Schedule) {
+ for (const cEvent *e = FirstEvent; e; e = Schedule->Events()->Next(e)) {
+ if (e->Vps() == startTime) {
+ ExpireTime = e->EndTime() + EXPIRELATENCY;
+ dsyslog("timer %s is waiting for next VPS event %s", *ToDescr(), *e->ToDescr());
+ break;
+ }
+ }
+ }
+ }
+ else {
+ dsyslog("timer %s has no event, setting expiration to +24h", *ToDescr());
+ ExpireTime += 3600 * 24;
+ }
+ }
+ }
+ return ExpireTime <= Now;
}
return false;
}

26
vdr-channel+epg.patch Normal file
View file

@ -0,0 +1,26 @@
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());

11
vdr-gcc7-fix.patch Normal file
View file

@ -0,0 +1,11 @@
--- 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');
}

View file

@ -0,0 +1,306 @@
#! /bin/sh /usr/share/dpatch/dpatch-run
## opt-41-x_timer-info.dpatch by Andreas Brugger <brougs78@gmx.net>, Thomas Günther <tom@toms-cafe.de>
## 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 <tom@toms-cafe.de>
+ - 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 <tom@toms-cafe.de>
+ - 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 <tom@toms-cafe.de>
+ - 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 <tg@e-tobi.net>
+ - 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 <tom@toms-cafe.de>
+ - 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 <tg@e-tobi.net>
+ - 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 <tom@toms-cafe.de>
+ - 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 <tom@toms-cafe.de>
+ - 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<cTimerEntry> 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)

View file

@ -0,0 +1,15 @@
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

View file

@ -0,0 +1,110 @@
--- 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()<Count()) {
+ // timer was deleted
+ cOsdMenu::Del(Current());
+ Display();
+ }
if (Key != kNone)
SetHelpKeys();
return state;

View file

@ -11,7 +11,6 @@ Type=notify
ExecStartPre=/usr/lib/vdr/bin/vdr-check-setup
ExecStart=/usr/sbin/runvdr
ExecStop=-/usr/lib/vdr/bin/vdr-set-wakeup
WatchdogSec=60
Restart=on-failure
RestartPreventExitStatus=2

376
vdr.spec
View file

@ -1,14 +1,10 @@
# TODO, maybe some day:
# - livebuffer patch, http://www.vdr-portal.de/board/thread.php?threadid=37309
# - channelfilter patch, http://www.u32.de/vdr.html#patches
# - more rofa's patches, http://www.saunalahti.fi/~rahrenbe/vdr/patches/
# - pause patch (causes OSD placement issues at least with unrebuilt text2skin)
# http://www.tolleri.net/vdr/vdr/vdr-1.6.0-2-pause-0.0.1.patch
# - The dvbhddevice plugin is no longer part of the VDR source archive.
# You can get the latest version of this plugin from the author's repository at
# https://bitbucket.org/powARman/dvbhddevice.
# - The dvbsddevice and rcu plugins are no longer part of the VDR source archive.
# You can get the latest versions of these plugins from ftp://ftp.tvdr.de/vdr/Plugins.
# http://thread.gmane.org/gmane.linux.vdr/40188
%{!?_pkgdocdir: %global _pkgdocdir %{_docdir}/%{name}-%{version}}
%global _hardened_build 1
@ -20,22 +16,20 @@
%global plugindir %{_libdir}/vdr
%global configdir %{_sysconfdir}/vdr
%global cachedir %{_var}/cache/vdr
%global rundir /run/vdr
%global rundir %{_var}/run/vdr
%global vdr_user vdr
%global vdr_group video
# From APIVERSION in config.h
%global apiver 9
%global apiver 2.2.0
Name: vdr
Version: 2.7.7
Release: 1%{?dist}
Version: 2.2.0
Release: 14%{?dist}
Summary: Video Disk Recorder
License: GPL-2.0-or-later
License: GPLv2+
URL: http://www.tvdr.de/
# Get vdr source from http://git.tvdr.de/?p=vdr.git;a=snapshot;h=refs/tags/2.7.7;sf=tbz2
# wget --content-disposition "http://git.tvdr.de/?p=vdr.git;a=snapshot;h=refs/tags/2.7.7;sf=tbz2"
Source0: %{name}-%{version}.tar.bz2
Source0: ftp://ftp.tvdr.de/vdr/%{name}-%{version}.tar.bz2
Source1: %{name}.service
Source2: %{name}.sysconfig
Source3: %{name}.sudoers
@ -56,27 +50,37 @@ Source18: http://cdn.debian.net/debian/pool/main/v/vdr/vdr_2.2.0-5.debian.
Source19: %{name}-check-setup.sh
Source20: %{name}-rcu.conf
Source21: %{name}-set-wakeup.sh
Source30: https://bitbucket.org/powARman/dvbhddevice/get/3473a7b939d7.zip
Source31: ftp://ftp.tvdr.de/vdr/Plugins/vdr-dvbsddevice-2.2.0.tgz
Source32: ftp://ftp.tvdr.de/vdr/Plugins/vdr-rcu-2.2.0.tgz
Patch0: define_AUDIO_GET_PTS.patch
Patch0: %{name}-channel+epg.patch
Patch1: http://zap.tartarus.org/~ds/debian/dists/stable/main/source/vdr_1.4.5-2.ds.diff.gz
Patch2: http://www.saunalahti.fi/~rahrenbe/vdr/patches/vdr-2.4.6-editrecording.patch.gz
Patch2: http://www.saunalahti.fi/~rahrenbe/vdr/patches/vdr-2.2.0-editrecording.patch.gz
# Extracted from http://copperhead.htpc-forum.de/downloads/extensionpatch/extpngvdr1.7.21v1.diff.gz
Patch3: %{name}-1.7.21-plugin-missing.patch
Patch4: %{name}-2.4.0-paths.patch
# http://vdrportal.de/board/thread.php?postid=343665#post343665
Patch5: 12_osdbase-maxitems.patch
# https://www.vdr-portal.de/forum/thread/135091-installation-eines-vdr-plugins-nativ-auf-coreelec-boxen/?postID=1379567#post1379567
Patch11: MainMenuHooks-v1_0_4.diff.txt
Patch15: %{name}-2.7.4-fedora-pkgconfig.patch
# https://www.vdr-portal.de/index.php?attachment/44831-vdr-2-4-6-clearobsoletechannels-diff
Patch99: %{name}-2.4.6-ClearObsoleteChannels2.diff
Patch4: %{name}-1.7.41-paths.patch
Patch5: http://toms-cafe.de/vdr/download/vdr-timer-info-0.5-1.7.13.diff
# http://article.gmane.org/gmane.linux.vdr/36097
Patch6: %{name}-1.5.18-syncearly.patch
Patch7: http://projects.vdr-developer.org/projects/plg-ttxtsubs/repository/revisions/master/raw/patches/vdr-2.2.0-ttxtsubs.patch
Patch8: http://www.saunalahti.fi/~rahrenbe/vdr/patches/vdr-2.2.0-lcn-support-v2.patch.gz
# http://www.udo-richter.de/vdr/patches.en.html#hlcutter
Patch9: http://www.udo-richter.de/vdr/files/vdr-1.7.29-hlcutter-0.2.3.diff
# http://www.udo-richter.de/vdr/naludump.en.html
Patch10: http://www.udo-richter.de/vdr/files/vdr-2.1.5-naludump-0.1.diff
# http://article.gmane.org/gmane.linux.vdr/43590
Patch11: %{name}-2.0.4-mainmenuhooks101.patch
# http://projects.vdr-developer.org/git/vdr-plugin-epgsearch.git/plain/patches/timercmd-0.1_1.7.17.diff
# Modified so that it applies over the timer-info patch
Patch12: %{name}-1.7.21-timercmd.patch
Patch13: http://projects.vdr-developer.org/git/vdr-plugin-epgsearch.git/plain/patches/vdr-1.5.17-progressbar-support-0.0.1.diff
# Sent upstream 2016-06-17
Patch14: 0001-Fix-build-with-systemd-230.patch
Patch15: %{name}-1.7.37-fedora-pkgconfig.patch
Patch17: http://projects.vdr-developer.org/git/vdr-plugin-epgsearch.git/plain/patches/vdr.epgsearch-exttimeredit-0.0.2.diff
Patch18: %{name}-timer-info-2.2.0.patch
Patch19: http://www.saunalahti.fi/~rahrenbe/vdr/patches/vdr-2.2.0-menuselection.patch.gz
# Extracted from https://www.linuxtv.org/pipermail/vdr/2017-March/029229.html
Patch20: %{name}-2.3.2-unsignedtosigned.diff
Patch21: %{name}-gcc7-fix.patch
BuildRequires: make
BuildRequires: gcc
BuildRequires: gcc-c++
BuildRequires: libjpeg-devel
BuildRequires: libcap-devel
BuildRequires: pkgconfig
@ -90,7 +94,7 @@ BuildRequires: systemd-devel
%if %{with docs}
BuildRequires: doxygen
BuildRequires: graphviz
%endif
%endif # docs
# udev >= 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
@ -98,6 +102,8 @@ 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}
@ -112,7 +118,7 @@ is required to run VDR.
%package devel
Summary: Development files for VDR
Requires: gettext-runtime
Requires: gettext
Provides: vdr-devel(api) = %{apiver}
%description devel
@ -164,27 +170,18 @@ window, using only plain text output.
%prep
%setup -q -a 18
# 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
%patch0 -p1
%patch1 -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
%patch 2 -p1
%patch 3 -p1
# 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
sed \
-e 's|__CACHEDIR__|%{cachedir}|' \
-e 's|__CONFIGDIR__|%{configdir}|' \
@ -192,16 +189,27 @@ sed \
-e 's|__VARDIR__|%{vardir}|' \
-e 's|__VIDEODIR__|%{videodir}|' \
%{PATCH4} | %{__patch} -p1
%patch 5 -p1
%patch 11 -p1
%patch 15 -p1
%patch 99 -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 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 \
for f in CONTRIBUTORS HISTORY UPDATE-1.4.0 README.timer-info \
PLUGINS/src/dvbhddevice/HISTORY; do
iconv -f iso-8859-1 -t utf-8 -o $f.utf8 $f && mv $f.utf8 $f
done
@ -232,15 +240,9 @@ 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 <<EOF
u vdr -:%{vdr_group} 'Video Disk Recorder' %{vardir} -
m vdr audio
m vdr cdrom
m vdr dialout
EOF
%build
cat << EOF > Make.config
CC = %{__cc}
CXX = %{__cxx}
@ -264,7 +266,6 @@ 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
@ -298,10 +299,11 @@ done
%if %{with docs}
%make_build srcdoc
%endif
%endif # docs
%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
@ -311,12 +313,7 @@ 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}
# 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
mv $RPM_BUILD_ROOT%{_bindir}/vdr $RPM_BUILD_ROOT%{_sbindir}
install -dm 755 $RPM_BUILD_ROOT%{configdir}/plugins
@ -417,7 +414,6 @@ echo "d %{rundir} 0755 %{vdr_user} root -" \
echo "%{_prefix}/lib/tmpfiles.d/%{name}.conf" \
>> %{name}.lang
# plugins
%make_install -C PLUGINS/src/dvbhddevice
@ -438,8 +434,6 @@ 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
@ -448,9 +442,14 @@ 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
@ -499,14 +498,13 @@ systemctl daemon-reload
%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
%endif # with docs
%{_bindir}/vdr-config
%{_bindir}/vdr-newplugin
%{_includedir}/libsi/
@ -552,226 +550,6 @@ systemctl daemon-reload
%changelog
* Fri Jul 25 2025 Martin Gansser <martinkg@fedoraproject.org> - 2.7.7-1
- Update to 2.7.7
* Fri Jul 25 2025 Fedora Release Engineering <releng@fedoraproject.org> - 2.7.6-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
* Sat Jun 21 2025 Martin Gansser <martinkg@fedoraproject.org> - 2.7.6-1
- Update to 2.7.6
* Tue May 27 2025 Martin Gansser <martinkg@fedoraproject.org> - 2.7.5-1
- Update to 2.7.5
- Add vdr-2.7.5-override-keyword.patch
* Sun May 11 2025 Peter Bieringer <pb@bieringer.de> - 2.7.4-3
- Re-add MainMenuHooks patch for 2.7.x
* Thu Apr 24 2025 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 2.7.4-2
- Add sysusers.d config file to allow rpm to create users/groups automatically
* Wed Feb 26 2025 Martin Gansser <martinkg@fedoraproject.org> - 2.7.4-1
- Update to 2.7.4
- Add vdr-2.7.4-fedora-pkgconfig.patch
* Fri Jan 24 2025 Martin Gansser <martinkg@fedoraproject.org> - 2.7.3-3
- Fix FTBFS #2341505
* Sun Jan 19 2025 Fedora Release Engineering <releng@fedoraproject.org> - 2.7.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild
* Mon Oct 14 2024 Martin Gansser <martinkg@fedoraproject.org> - 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 <releng@fedoraproject.org> - 2.6.9-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild
* Mon Jul 15 2024 Martin Gansser <martinkg@fedoraproject.org> - 2.6.9-1
- Update to 2.6.9
* Sun Jul 14 2024 Martin Gansser <martinkg@fedoraproject.org> - 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 <martinkg@fedoraproject.org> - 2.6.8-1
- Update to 2.6.8
- Add strreplace.patch
* Tue Apr 02 2024 Martin Gansser <martinkg@fedoraproject.org> - 2.6.7-1
- Update to 2.6.7
* Fri Jan 26 2024 Martin Gansser <martinkg@fedoraproject.org> - 2.6.6-1
- Update to 2.6.6
* Wed Jan 03 2024 Martin Gansser <martinkg@fedoraproject.org> - 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 <releng@fedoraproject.org> - 2.6.4-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
* Mon Feb 20 2023 Martin Gansser <martinkg@fedoraproject.org> - 2.6.4-1
- Update to 2.6.4
* Fri Feb 10 2023 Fedora Release Engineering <releng@fedoraproject.org> - 2.6.3-3
- Rebuilt for rawhide
* Sat Jan 21 2023 Fedora Release Engineering <releng@fedoraproject.org> - 2.6.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
* Wed Dec 14 2022 Martin Gansser <martinkg@fedoraproject.org> - 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 <martinkg@fedoraproject.org> - 2.6.2-2
- Add vdr-2.6.2-index-file-regeneration-failed.patch
* Wed Nov 30 2022 Martin Gansser <martinkg@fedoraproject.org> - 2.6.2-1
- Update to 2.6.2
- Add vdr-2.6.2-remux.patch
* Sat Jul 23 2022 Fedora Release Engineering <releng@fedoraproject.org> - 2.6.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
* Thu Feb 03 2022 Martin Gansser <martinkg@fedoraproject.org> - 2.6.1-1
- Update to 2.6.1
* Sat Jan 29 2022 Martin Gansser <martinkg@fedoraproject.org> - 2.6.0-4
- Add vdr-2.6.0-fix-dvbplayer.diff
- Add %%undefine _package_note_flags
* Sat Jan 22 2022 Fedora Release Engineering <releng@fedoraproject.org> - 2.6.0-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
* Mon Jan 03 2022 Martin Gansser <martinkg@fedoraproject.org> - 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 <martinkg@fedoraproject.org> - 2.6.0-1
- Update to 2.6.0
* Wed Dec 29 2021 Martin Gansser <martinkg@fedoraproject.org> - 2.4.8-1
- Update to 2.4.8
* Thu Oct 21 2021 Martin Gansser <martinkg@fedoraproject.org> - 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 <martinkg@fedoraproject.org> - 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 <releng@fedoraproject.org> - 2.4.7-3
- Second attempt - Rebuilt for
https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
* Sat Jun 12 2021 Martin Gansser <martinkg@fedoraproject.org> - 2.4.7-2
- Add vdr-2.4.7_gcc11.patch
* Fri Apr 23 2021 Martin Gansser <martinkg@fedoraproject.org> - 2.4.7-1
- Update to 2.4.7
* Tue Feb 09 2021 Martin Gansser <martinkg@fedoraproject.org> - 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 <releng@fedoraproject.org> - 2.4.6-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
* Fri Jan 22 2021 Martin Gansser <martinkg@fedoraproject.org> - 2.4.6-5
- Add modified vdr-2.4.4-RecordingInfo.patch for extrecmenung plugin
* Sat Jan 16 2021 Martin Gansser <martinkg@fedoraproject.org> - 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 <martinkg@fedoraproject.org> - 2.4.6-3
- Add modified vdr-2.4.6-ClearObsoleteChannels2.diff
* Sun Jan 03 2021 Martin Gansser <martinkg@fedoraproject.org> - 2.4.6-2
- Add vdr-2.4.6-ClearObsoleteChannels.diff
* Mon Dec 28 2020 Martin Gansser <martinkg@fedoraproject.org> - 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 <martinkg@fedoraproject.org> - 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 <martinkg@fedoraproject.org> - 2.4.1-8
- Rebuilt for rawhide
* Wed Jul 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.4.1-7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
* Sat Jun 27 2020 Martin Gansser <martinkg@fedoraproject.org> - 2.4.1-6
- Rebuilt for rawhide
* Fri Jan 31 2020 Fedora Release Engineering <releng@fedoraproject.org> - 2.4.1-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
* Sun Dec 15 2019 Martin Gansser <martinkg@fedoraproject.org> - 2.4.1-4
- Modify %%{name}-2.4.1-glibc231.patch
* Sat Dec 14 2019 Martin Gansser <martinkg@fedoraproject.org> - 2.4.1-3
- Add %%{name}-2.4.1-glibc231.patch
* Sat Jul 27 2019 Fedora Release Engineering <releng@fedoraproject.org> - 2.4.1-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
* Mon Jun 17 2019 Martin Gansser <martinkg@fedoraproject.org> - 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 <releng@fedoraproject.org> - 2.4.0-6
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
* Tue Nov 27 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 2.4.0-5
- Rebuild for tinyxml2 7.x
* Sun Oct 28 2018 Martin Gansser <martinkg@fedoraproject.org> - 2.4.0-4
- Re-add dvbsddevice Plugin
- Re-add rcu Plugin
* Fri Sep 28 2018 Martin Gansser <martinkg@fedoraproject.org> - 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 <releng@fedoraproject.org> - 2.4.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
* Mon Apr 16 2018 Martin Gansser <martinkg@fedoraproject.org> - 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 <ignatenkobrain@fedoraproject.org> - 2.2.0-14
- Escape macros in %%changelog

View file

@ -18,8 +18,6 @@ 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
@ -54,7 +52,7 @@ burn
# PATH where to find the internally used executables.
#
PATH="/usr/lib64/vdr/bin:$PATH"
PATH="/usr/lib/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