Compare commits
4 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d12d91235d | ||
|
|
6afb7dccf1 | ||
|
|
21947ffae1 | ||
|
|
88a515bfa6 |
34 changed files with 0 additions and 4246 deletions
|
|
@ -1,29 +0,0 @@
|
|||
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
|
||||
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
--- dvbhddevice/dvbhdffdevice.c.orig 2018-04-17 13:57:26.871268867 +0200
|
||||
+++ dvbhddevice/dvbhdffdevice.c 2018-04-17 13:58:45.698264299 +0200
|
||||
@@ -461,7 +461,8 @@
|
||||
const tTrackId *TrackId = GetTrack(Type);
|
||||
if (TrackId && TrackId->id) {
|
||||
int streamType = 0;
|
||||
- cChannel * channel = Channels.GetByNumber(CurrentChannel());
|
||||
+ LOCK_CHANNELS_READ;
|
||||
+ const cChannel * channel = Channels->GetByNumber(CurrentChannel());
|
||||
if (channel) {
|
||||
if (IS_AUDIO_TRACK(Type))
|
||||
streamType = channel->Atype(Type - ttAudioFirst);
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
diff -Naur vdr-2.4.7/PLUGINS/src/dvbhddevice/dvbhdffdevice.c vdr-2.4.7-new/PLUGINS/src/dvbhddevice/dvbhdffdevice.c
|
||||
--- vdr-2.4.7/PLUGINS/src/dvbhddevice/dvbhdffdevice.c 2018-04-20 22:23:47.000000000 +0200
|
||||
+++ vdr-2.4.7-new/PLUGINS/src/dvbhddevice/dvbhdffdevice.c 2021-08-03 14:22:36.172626332 +0200
|
||||
@@ -11,9 +11,9 @@
|
||||
#include <limits.h>
|
||||
#include <libsi/si.h>
|
||||
#include <linux/videodev2.h>
|
||||
-#include <linux/dvb/audio.h>
|
||||
+#include <../kernel-headers-5.13/audio.h>
|
||||
#include <linux/dvb/dmx.h>
|
||||
-#include <linux/dvb/video.h>
|
||||
+#include <../kernel-headers-5.13/video.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <vdr/eitscan.h>
|
||||
diff -Naur vdr-2.4.7/PLUGINS/src/dvbhddevice/hdffosd.c vdr-2.4.7-new/PLUGINS/src/dvbhddevice/hdffosd.c
|
||||
--- vdr-2.4.7/PLUGINS/src/dvbhddevice/hdffosd.c 2018-04-20 22:23:47.000000000 +0200
|
||||
+++ vdr-2.4.7-new/PLUGINS/src/dvbhddevice/hdffosd.c 2021-08-03 14:22:36.177626332 +0200
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "hdffosd.h"
|
||||
-#include <linux/dvb/osd.h>
|
||||
+#include <../kernel-headers-5.13/osd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include "hdffcmd.h"
|
||||
diff -Naur vdr-2.4.7/PLUGINS/src/dvbhddevice/dvbsdffosd.c vdr-2.4.7-new/PLUGINS/src/dvbhddevice/dvbsdffosd.c
|
||||
--- vdr-2.4.7/PLUGINS/src/dvbsddevice/dvbsdffosd.c 2011-04-17 14:55:09.000000000 +0200
|
||||
+++ vdr-2.4.7-new/PLUGINS/src/dvbsddevice/dvbsdffosd.c 2021-08-03 14:22:36.188626333 +0200
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
#include "dvbsdffosd.h"
|
||||
-#include <linux/dvb/osd.h>
|
||||
+#include <../kernel-headers-5.13/osd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/unistd.h>
|
||||
diff -Naur vdr-2.4.7/PLUGINS/src/dvbhddevice/libhdffcmd/hdffcmd_base.h vdr-2.4.7-new/PLUGINS/src/dvbhddevice/libhdffcmd/hdffcmd_base.h
|
||||
--- vdr-2.4.7/PLUGINS/src/dvbhddevice/libhdffcmd/hdffcmd_base.h 2018-04-20 22:23:47.000000000 +0200
|
||||
+++ vdr-2.4.7-new/PLUGINS/src/dvbhddevice/libhdffcmd/hdffcmd_base.h 2021-08-03 14:22:36.193626333 +0200
|
||||
@@ -24,7 +24,7 @@
|
||||
#ifndef HDFFCMD_BASE_H
|
||||
#define HDFFCMD_BASE_H
|
||||
|
||||
-#include <linux/dvb/osd.h>
|
||||
+#include <../kernel-headers-5.13/osd.h>
|
||||
|
||||
#if !defined OSD_RAW_CMD
|
||||
typedef struct osd_raw_cmd_s {
|
||||
diff -Naur vdr-2.4.7/PLUGINS/src/dvbsddevice/dvbsdffdevice.c vdr-2.4.7-new/PLUGINS/src/dvbsddevice/dvbsdffdevice.c
|
||||
--- vdr-2.4.7/PLUGINS/src/dvbsddevice/dvbsdffdevice.c 2014-03-15 13:35:21.000000000 +0100
|
||||
+++ vdr-2.4.7-new/PLUGINS/src/dvbsddevice/dvbsdffdevice.c 2021-08-03 14:22:36.203626334 +0200
|
||||
@@ -10,9 +10,9 @@
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <linux/videodev2.h>
|
||||
-#include <linux/dvb/audio.h>
|
||||
+#include <../kernel-headers-5.13/audio.h>
|
||||
#include <linux/dvb/dmx.h>
|
||||
-#include <linux/dvb/video.h>
|
||||
+#include <../kernel-headers-5.13/video.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <vdr/eitscan.h>
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
Description: This patch allows plugins to replace the VDR mainmenus "Schedule", "Channels", "Timers" and "Recordings" by a different implementation.
|
||||
Author: Frank Schmirler <vdrdev@schmirler.de>
|
||||
This is a "patch" for the Video Disk Recorder (VDR).
|
||||
|
||||
* History
|
||||
2012-04-06: Version 1.0.2
|
||||
- Update für aktuelle VDR-Entwickler-Versionen (Manuel Reimer)
|
||||
|
||||
2010-10-15: Version 1.0.1
|
||||
- return a cOsdObject instead of its subclass cOsdMenu (thanks to
|
||||
Joe_D@vdrportal)
|
||||
- version number defines in config.h now follow the ususal conventions:
|
||||
MAINMENUHOOKSVERSNUM is now a number, the newly added define
|
||||
MAINMENUHOOKSVERSION is a string (suggested by gnapheus@vdrportal)
|
||||
- patch is now based on VDR 1.6.0
|
||||
- updated documentation
|
||||
|
||||
2007-02-26: Version 1.0
|
||||
- Initial revision.
|
||||
|
||||
* Authors:
|
||||
Tobias Grimm <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.
|
||||
|
||||
Index: b/menu.c
|
||||
===================================================================
|
||||
--- a/menu.c
|
||||
+++ b/menu.c
|
||||
@@ -4620,15 +4620,31 @@
|
||||
|
||||
// Initial submenus:
|
||||
|
||||
+ cOsdObject *menu = NULL;
|
||||
switch (State) {
|
||||
- case osSchedule: AddSubMenu(new cMenuSchedule); break;
|
||||
- case osChannels: AddSubMenu(new cMenuChannels); break;
|
||||
- case osTimers: AddSubMenu(new cMenuTimers); break;
|
||||
- case osRecordings: AddSubMenu(new cMenuRecordings(NULL, 0, OpenSubMenus)); break;
|
||||
- case osSetup: AddSubMenu(new cMenuSetup); break;
|
||||
- case osCommands: AddSubMenu(new cMenuCommands(tr("Commands"), &Commands)); break;
|
||||
+ case osSchedule:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu))
|
||||
+ menu = new cMenuSchedule;
|
||||
+ break;
|
||||
+ case osChannels:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu))
|
||||
+ menu = new cMenuChannels;
|
||||
+ break;
|
||||
+ case osTimers:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu))
|
||||
+ menu = new cMenuTimers;
|
||||
+ break;
|
||||
+ case osRecordings:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu))
|
||||
+ menu = new cMenuRecordings(NULL, 0, true);
|
||||
+ break;
|
||||
+ case osSetup: menu = new cMenuSetup; break;
|
||||
+ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break;
|
||||
default: break;
|
||||
}
|
||||
+ if (menu)
|
||||
+ if (menu->IsMenu())
|
||||
+ AddSubMenu((cOsdMenu *) menu);
|
||||
}
|
||||
|
||||
cOsdObject *cMenuMain::PluginOsdObject(void)
|
||||
@@ -4765,13 +4781,34 @@
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
HadSubMenu |= HasSubMenu();
|
||||
|
||||
+ cOsdObject *menu = NULL;
|
||||
switch (state) {
|
||||
- case osSchedule: return AddSubMenu(new cMenuSchedule);
|
||||
- case osChannels: return AddSubMenu(new cMenuChannels);
|
||||
- case osTimers: return AddSubMenu(new cMenuTimers);
|
||||
- case osRecordings: return AddSubMenu(new cMenuRecordings);
|
||||
- case osSetup: return AddSubMenu(new cMenuSetup);
|
||||
- case osCommands: return AddSubMenu(new cMenuCommands(tr("Commands"), &Commands));
|
||||
+ case osSchedule:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu))
|
||||
+ menu = new cMenuSchedule;
|
||||
+ else
|
||||
+ state = osContinue;
|
||||
+ break;
|
||||
+ case osChannels:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu))
|
||||
+ menu = new cMenuChannels;
|
||||
+ else
|
||||
+ state = osContinue;
|
||||
+ break;
|
||||
+ case osTimers:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu))
|
||||
+ menu = new cMenuTimers;
|
||||
+ else
|
||||
+ state = osContinue;
|
||||
+ break;
|
||||
+ case osRecordings:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu))
|
||||
+ menu = new cMenuRecordings;
|
||||
+ else
|
||||
+ state = osContinue;
|
||||
+ break;
|
||||
+ case osSetup: menu = new cMenuSetup; break;
|
||||
+ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break;
|
||||
case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) {
|
||||
if (cOsdItem *item = Get(Current())) {
|
||||
cRecordControls::Stop(item->Text() + strlen(tr(STOP_RECORDING)));
|
||||
@@ -4857,6 +4894,12 @@
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
+ if (menu) {
|
||||
+ if (menu->IsMenu())
|
||||
+ return AddSubMenu((cOsdMenu *) menu);
|
||||
+ pluginOsdObject = menu;
|
||||
+ return osPlugin;
|
||||
+ }
|
||||
if (!HasSubMenu() && Update(HadSubMenu))
|
||||
Display();
|
||||
if (Key != kNone) {
|
||||
Index: b/config.h
|
||||
===================================================================
|
||||
--- a/config.h
|
||||
+++ b/config.h
|
||||
@@ -36,6 +36,10 @@
|
||||
// plugins to work with newer versions of the core VDR as long as no
|
||||
// VDR header files have changed.
|
||||
|
||||
+// The MainMenuHook Patch's version number:
|
||||
+#define MAINMENUHOOKSVERSION "1.0.1"
|
||||
+#define MAINMENUHOOKSVERSNUM 10001 // Version * 10000 + Major * 100 + Minor
|
||||
+
|
||||
#define MAXPRIORITY 99
|
||||
#define MINPRIORITY (-MAXPRIORITY)
|
||||
#define LIVEPRIORITY 0 // priority used when selecting a device for live viewing
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
Description: Log an error message when skincures can't initialize the screen
|
||||
Author: Tobias Grimm <etobi@debian.org>
|
||||
|
||||
--- a/PLUGINS/src/skincurses/skincurses.c
|
||||
+++ b/PLUGINS/src/skincurses/skincurses.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <vdr/plugin.h>
|
||||
#include <vdr/skins.h>
|
||||
#include <vdr/videodir.h>
|
||||
+#include <vdr/tools.h>
|
||||
|
||||
static const char *VERSION = "2.4.0";
|
||||
static const char *DESCRIPTION = trNOOP("A text only skin");
|
||||
@@ -833,6 +834,7 @@
|
||||
ScOsdHeight = w->_maxy - w->_begy + 1;
|
||||
return true;
|
||||
}
|
||||
+ esyslog("skincurses: unable to initialize curses screen");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1,106 +0,0 @@
|
|||
diff -Nru vdr-1.5.17-orig/skinclassic.c vdr-1.5.17-progressbar/skinclassic.c
|
||||
--- vdr-1.5.17-orig/skinclassic.c
|
||||
+++ vdr-1.5.17-progressbar/skinclassic.c
|
||||
@@ -314,8 +314,47 @@
|
||||
for (int i = 0; i < MaxTabs; i++) {
|
||||
const char *s = GetTabbedText(Text, i);
|
||||
if (s) {
|
||||
- int xt = x0 + Tab(i);
|
||||
- osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x2 - xt);
|
||||
+ bool isprogressbar = false;
|
||||
+ int now = 0, total = 0;
|
||||
+ // check if progress bar: "[||||||| ]"
|
||||
+ if ((strlen(s) > 5 && s[0] == '[' && s[strlen(s) - 1] == ']')) {
|
||||
+ const char *p = s + 1;
|
||||
+ // update status
|
||||
+ isprogressbar = true;
|
||||
+ for (; *p != ']'; ++p) {
|
||||
+ // check if progressbar characters
|
||||
+ if (*p == ' ' || *p == '|') {
|
||||
+ // update counters
|
||||
+ ++total;
|
||||
+ if (*p == '|')
|
||||
+ ++now;
|
||||
+ }
|
||||
+ else {
|
||||
+ // wrong character detected; not a progressbar
|
||||
+ isprogressbar = false;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ int xt = x0 + Tab(i);
|
||||
+ if (isprogressbar) {
|
||||
+ // define x coordinates of progressbar
|
||||
+ int px0 = xt;
|
||||
+ int px1 = (Tab(i + 1)?Tab(i+1):x1) - 5;
|
||||
+ int px = px0 + max((int)((float) now * (float) (px1 - px0) / (float) total), 1);
|
||||
+ // define y coordinates of progressbar
|
||||
+ int py0 = y + 4;
|
||||
+ int py1 = y + lineHeight - 4;
|
||||
+ // draw background
|
||||
+ osd->DrawRectangle(px0, y, (Tab(i + 1)?Tab(i+1):x1) - 1, y + lineHeight - 1, ColorBg);
|
||||
+ // draw progressbar
|
||||
+ osd->DrawRectangle(px0, py0, px, py1, ColorFg);
|
||||
+ osd->DrawRectangle(px + 1, py0, px1, py0 + 1, ColorFg);
|
||||
+ osd->DrawRectangle(px + 1, py1 - 1, px1, py1, ColorFg);
|
||||
+ osd->DrawRectangle(px1 - 1, py0, px1, py1, ColorFg);
|
||||
+ }
|
||||
+ else
|
||||
+ osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x2 - xt);
|
||||
}
|
||||
if (!Tab(i + 1))
|
||||
break;
|
||||
diff -Nru vdr-1.5.17-orig/skinsttng.c vdr-1.5.17-progressbar/skinsttng.c
|
||||
--- vdr-1.5.17-orig/skinsttng.c
|
||||
+++ vdr-1.5.17-progressbar/skinsttng.c
|
||||
@@ -558,8 +558,47 @@
|
||||
for (int i = 0; i < MaxTabs; i++) {
|
||||
const char *s = GetTabbedText(Text, i);
|
||||
if (s) {
|
||||
- int xt = x3 + 5 + Tab(i);
|
||||
- osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x4 - xt);
|
||||
+ bool isprogressbar = false;
|
||||
+ int now = 0, total = 0;
|
||||
+ // check if progress bar: "[||||||| ]"
|
||||
+ if ((strlen(s) > 5 && s[0] == '[' && s[strlen(s) - 1] == ']')) {
|
||||
+ const char *p = s + 1;
|
||||
+ // update status
|
||||
+ isprogressbar = true;
|
||||
+ for (; *p != ']'; ++p) {
|
||||
+ // check if progressbar characters
|
||||
+ if (*p == ' ' || *p == '|') {
|
||||
+ // update counters
|
||||
+ ++total;
|
||||
+ if (*p == '|')
|
||||
+ ++now;
|
||||
+ }
|
||||
+ else {
|
||||
+ // wrong character detected; not a progressbar
|
||||
+ isprogressbar = false;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ int xt = x3 + 5 + Tab(i);
|
||||
+ if (isprogressbar) {
|
||||
+ // define x coordinates of progressbar
|
||||
+ int px0 = xt;
|
||||
+ int px1 = x3 + (Tab(i + 1)?Tab(i + 1):x4-x3-5) - 1;
|
||||
+ int px = px0 + max((int)((float) now * (float) (px1 - px0) / (float) total), 1);
|
||||
+ // define y coordinates of progressbar
|
||||
+ int py0 = y + 4;
|
||||
+ int py1 = y + lineHeight - 4;
|
||||
+ // draw background
|
||||
+ osd->DrawRectangle(px0, y, (Tab(i + 1)?Tab(i + 1):x4-x3-5) - 1, y + lineHeight - 1, ColorBg);
|
||||
+ // draw progressbar
|
||||
+ osd->DrawRectangle(px0, py0, px, py1, ColorFg);
|
||||
+ osd->DrawRectangle(px + 1, py0, px1, py0 + 1, ColorFg);
|
||||
+ osd->DrawRectangle(px + 1, py1 - 1, px1, py1, ColorFg);
|
||||
+ osd->DrawRectangle(px1 - 1, py0, px1, py1, ColorFg);
|
||||
+ }
|
||||
+ else
|
||||
+ osd->DrawText(xt, y, s, ColorFg, ColorBg, font, x4 - xt);
|
||||
}
|
||||
if (!Tab(i + 1))
|
||||
break;
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
Sync early parts extracted from the non-dvbs2 patch at
|
||||
http://article.gmane.org/gmane.linux.vdr/36097, fprintf(stderr) calls
|
||||
changed to dsyslog().
|
||||
|
||||
diff -Nurp ../vdr-1.5.18-orig/device.c ./device.c
|
||||
--- ../vdr-1.5.18-orig/device.c 2008-03-09 11:03:34.000000000 +0100
|
||||
+++ ./device.c 2008-03-19 22:34:40.000000000 +0100
|
||||
@@ -840,7 +840,7 @@ eSetChannelResult cDevice::SetChannel(co
|
||||
}
|
||||
for (int i = 0; i < MAXSPIDS; i++)
|
||||
SetAvailableTrack(ttSubtitle, i, Channel->Spid(i), Channel->Slang(i));
|
||||
- if (!NeedsTransferMode)
|
||||
+ if (!NeedsTransferMode || GetCurrentAudioTrack() == ttNone)
|
||||
EnsureAudioTrack(true);
|
||||
EnsureSubtitleTrack();
|
||||
}
|
||||
diff -Nurp ../vdr-1.5.18-orig/remux.c ./remux.c
|
||||
--- ../vdr-1.5.18-orig/remux.c 2007-11-25 14:56:03.000000000 +0100
|
||||
+++ ./remux.c 2008-02-24 19:47:40.000000000 +0100
|
||||
@@ -1896,12 +2526,13 @@ int cRingBufferLinearPes::DataReady(cons
|
||||
|
||||
#define RESULTBUFFERSIZE KILOBYTE(256)
|
||||
|
||||
-cRemux::cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure)
|
||||
+cRemux::cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure, bool SyncEarly)
|
||||
{
|
||||
exitOnFailure = ExitOnFailure;
|
||||
noVideo = VPid == 0 || VPid == 1 || VPid == 0x1FFF;
|
||||
numUPTerrors = 0;
|
||||
synced = false;
|
||||
+ syncEarly = SyncEarly;
|
||||
skipped = 0;
|
||||
numTracks = 0;
|
||||
resultSkipped = 0;
|
||||
@@ -2105,12 +2840,14 @@ uchar *cRemux::Get(int &Count, uchar *Pi
|
||||
}
|
||||
}
|
||||
else if (!synced) {
|
||||
- if (pt == I_FRAME) {
|
||||
+ if (pt == I_FRAME || syncEarly) {
|
||||
if (PictureType)
|
||||
*PictureType = pt;
|
||||
resultSkipped = i; // will drop everything before this position
|
||||
- SetBrokenLink(data + i, l);
|
||||
synced = true;
|
||||
+ if (pt == I_FRAME) // syncEarly: it's ok but there is no need to call SetBrokenLink()
|
||||
+ SetBrokenLink(data + i, l);
|
||||
+else dsyslog("video: synced early");
|
||||
}
|
||||
}
|
||||
else if (Count)
|
||||
@@ -2123,17 +2860,19 @@ uchar *cRemux::Get(int &Count, uchar *Pi
|
||||
l = GetPacketLength(data, resultCount, i);
|
||||
if (l < 0)
|
||||
return resultData;
|
||||
- if (noVideo) {
|
||||
+ if (noVideo || !synced && syncEarly) {
|
||||
+ uchar pt = NO_PICTURE;
|
||||
if (!synced) {
|
||||
- if (PictureType)
|
||||
- *PictureType = I_FRAME;
|
||||
+ if (PictureType && noVideo)
|
||||
+ *PictureType = pt;
|
||||
resultSkipped = i; // will drop everything before this position
|
||||
synced = true;
|
||||
+if (!noVideo) dsyslog("audio: synced early");
|
||||
}
|
||||
else if (Count)
|
||||
return resultData;
|
||||
else if (PictureType)
|
||||
- *PictureType = I_FRAME;
|
||||
+ *PictureType = pt;
|
||||
}
|
||||
}
|
||||
if (synced) {
|
||||
diff -Nurp ../vdr-1.5.18-orig/remux.h ./remux.h
|
||||
--- ../vdr-1.5.18-orig/remux.h 2007-09-02 12:19:06.000000000 +0200
|
||||
+++ ./remux.h 2008-02-24 19:47:40.000000000 +0100
|
||||
@@ -40,6 +40,7 @@
|
||||
bool noVideo;
|
||||
int numUPTerrors;
|
||||
bool synced;
|
||||
+ bool syncEarly;
|
||||
int skipped;
|
||||
cTS2PES *ts2pes[MAXTRACKS];
|
||||
int numTracks;
|
||||
@@ -47,12 +48,13 @@
|
||||
int resultSkipped;
|
||||
int GetPid(const uchar *Data);
|
||||
public:
|
||||
- cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure = false);
|
||||
+ cRemux(int VPid, const int *APids, const int *DPids, const int *SPids, bool ExitOnFailure = false, bool SyncEarly = false);
|
||||
///< Creates a new remuxer for the given PIDs. VPid is the video PID, while
|
||||
///< APids, DPids and SPids are pointers to zero terminated lists of audio,
|
||||
///< dolby and subtitle PIDs (the pointers may be NULL if there is no such
|
||||
///< PID). If ExitOnFailure is true, the remuxer will initiate an "emergency
|
||||
- ///< exit" in case of problems with the data stream.
|
||||
+ ///< exit" in case of problems with the data stream. SyncEarly causes cRemux
|
||||
+ ///< to sync as soon as a video or audio frame is seen.
|
||||
~cRemux();
|
||||
void SetTimeouts(int PutTimeout, int GetTimeout) { resultBuffer->SetTimeouts(PutTimeout, GetTimeout); }
|
||||
///< By default cRemux assumes that Put() and Get() are called from different
|
||||
diff -Nurp ../vdr-1.5.18-orig/transfer.c ./transfer.c
|
||||
--- ../vdr-1.5.18-orig/transfer.c 2007-01-05 11:45:28.000000000 +0100
|
||||
+++ ./transfer.c 2008-02-24 19:47:40.000000000 +0100
|
||||
@@ -19,7 +19,7 @@ cTransfer::cTransfer(tChannelID ChannelI
|
||||
,cThread("transfer")
|
||||
{
|
||||
ringBuffer = new cRingBufferLinear(TRANSFERBUFSIZE, TS_SIZE * 2, true, "Transfer");
|
||||
- remux = new cRemux(VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids);
|
||||
+ remux = new cRemux(VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids, false, true);
|
||||
}
|
||||
|
||||
cTransfer::~cTransfer()
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
diff -up vdr-1.7.21/config.c~ vdr-1.7.21/config.c
|
||||
--- vdr-1.7.21/config.c~ 2011-10-18 00:02:51.394223695 +0300
|
||||
+++ vdr-1.7.21/config.c 2011-10-18 00:12:30.255855027 +0300
|
||||
@@ -211,6 +211,7 @@ bool cNestedItemList::Save(void)
|
||||
cNestedItemList Folders;
|
||||
cNestedItemList Commands;
|
||||
cNestedItemList RecordingCommands;
|
||||
+cNestedItemList TimerCommands;
|
||||
|
||||
// --- cSVDRPhosts -----------------------------------------------------------
|
||||
|
||||
diff -up vdr-1.7.21/config.h~ vdr-1.7.21/config.h
|
||||
--- vdr-1.7.21/config.h~ 2011-10-18 00:02:51.438227770 +0300
|
||||
+++ vdr-1.7.21/config.h 2011-10-18 00:12:30.702896536 +0300
|
||||
@@ -187,6 +187,7 @@ public:
|
||||
extern cNestedItemList Folders;
|
||||
extern cNestedItemList Commands;
|
||||
extern cNestedItemList RecordingCommands;
|
||||
+extern cNestedItemList TimerCommands;
|
||||
extern cSVDRPhosts SVDRPhosts;
|
||||
|
||||
class cSetupLine : public cListObject {
|
||||
diff -up vdr-1.7.21/menu.c~ vdr-1.7.21/menu.c
|
||||
--- vdr-1.7.21/menu.c~ 2011-10-18 00:02:51.428226843 +0300
|
||||
+++ vdr-1.7.21/menu.c 2011-10-18 00:12:29.520786768 +0300
|
||||
@@ -1142,6 +1142,7 @@ void cTimerEntry::SetDiskStatus(char Dis
|
||||
|
||||
class cMenuTimers : public cOsdMenu {
|
||||
private:
|
||||
+ eOSState Commands(eKeys Key = kNone);
|
||||
int helpKeys;
|
||||
eOSState Edit(void);
|
||||
eOSState New(void);
|
||||
@@ -1259,6 +1260,53 @@ eOSState cMenuTimers::Delete(void)
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
+#define CHECK_2PTR_NULL(x_,y_) ((x_)? ((y_)? y_:""):"")
|
||||
+
|
||||
+eOSState cMenuTimers::Commands(eKeys Key)
|
||||
+{
|
||||
+ if (HasSubMenu() || Count() == 0)
|
||||
+ return osContinue;
|
||||
+ cTimer *ti = CurrentTimer();
|
||||
+ if (ti) {
|
||||
+ char *parameter = NULL;
|
||||
+ const cEvent *pEvent = ti->Event();
|
||||
+ int iRecNumber=0;
|
||||
+
|
||||
+ if(!pEvent) {
|
||||
+ Timers.SetEvents();
|
||||
+ pEvent = ti->Event();
|
||||
+ }
|
||||
+ if(pEvent) {
|
||||
+// create a dummy recording to get the real filename
|
||||
+ cRecording *rc_dummy = new cRecording(ti, pEvent);
|
||||
+ Recordings.Load();
|
||||
+ cRecording *rc = Recordings.GetByName(rc_dummy->FileName());
|
||||
+
|
||||
+ delete rc_dummy;
|
||||
+ if(rc)
|
||||
+ iRecNumber=rc->Index() + 1;
|
||||
+ }
|
||||
+//Parameter format TimerNumber 'ChannelId' Start Stop 'Titel' 'Subtitel' 'file' RecNumer
|
||||
+// 1 2 3 4 5 6 7 8
|
||||
+ asprintf(¶meter, "%d '%s' %d %d '%s' '%s' '%s' %d", ti->Index(),
|
||||
+ *ti->Channel()->GetChannelID().ToString(),
|
||||
+ (int)ti->StartTime(),
|
||||
+ (int)ti->StopTime(),
|
||||
+ CHECK_2PTR_NULL(pEvent, pEvent->Title()),
|
||||
+ CHECK_2PTR_NULL(pEvent, pEvent->ShortText()),
|
||||
+ ti->File(),
|
||||
+ iRecNumber);
|
||||
+ isyslog("timercmd: %s", parameter);
|
||||
+ cMenuCommands *menu;
|
||||
+ eOSState state = AddSubMenu(menu = new cMenuCommands(tr("Timer commands"), &TimerCommands, parameter));
|
||||
+ free(parameter);
|
||||
+ if (Key != kNone)
|
||||
+ state = menu->ProcessKey(Key);
|
||||
+ return state;
|
||||
+ }
|
||||
+ return osContinue;
|
||||
+}
|
||||
+
|
||||
eOSState cMenuTimers::Info(void)
|
||||
{
|
||||
if (HasSubMenu() || Count() == 0)
|
||||
@@ -1346,6 +1394,8 @@ eOSState cMenuTimers::ProcessKey(eKeys K
|
||||
case kInfo:
|
||||
case kBlue: return Info();
|
||||
break;
|
||||
+ case k1...k9: return Commands(Key);
|
||||
+ case k0: return (TimerCommands.Count()? Commands():osContinue);
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
diff -up vdr-1.7.21/vdr.c~ vdr-1.7.21/vdr.c
|
||||
--- vdr-1.7.21/vdr.c~ 2011-10-18 00:02:51.284213503 +0300
|
||||
+++ vdr-1.7.21/vdr.c 2011-10-18 00:12:31.901007794 +0300
|
||||
@@ -602,6 +602,7 @@ int main(int argc, char *argv[])
|
||||
Timers.Load(AddDirectory(ConfigDirectory, "timers.conf"));
|
||||
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"));
|
||||
RecordingCommands.Load(AddDirectory(ConfigDirectory, "reccmds.conf"));
|
||||
+ TimerCommands.Load(AddDirectory(ConfigDirectory, "timercmds.conf"));
|
||||
SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true);
|
||||
Keys.Load(AddDirectory(ConfigDirectory, "remote.conf"));
|
||||
KeyMacros.Load(AddDirectory(ConfigDirectory, "keymacros.conf"), true);
|
||||
|
|
@ -1,612 +0,0 @@
|
|||
diff -Naur vdr-1.7.27/config.c vdr-1.7.27-hlcutter/config.c
|
||||
--- vdr-1.7.27/config.c 2012-02-29 11:15:54.000000000 +0100
|
||||
+++ vdr-1.7.27-hlcutter/config.c 2012-03-31 13:25:56.000000000 +0200
|
||||
@@ -445,8 +445,10 @@
|
||||
FontSmlSize = 18;
|
||||
FontFixSize = 20;
|
||||
MaxVideoFileSize = MAXVIDEOFILESIZEDEFAULT;
|
||||
+ MaxRecordingSize = DEFAULTRECORDINGSIZE;
|
||||
SplitEditedFiles = 0;
|
||||
DelTimeshiftRec = 0;
|
||||
+ HardLinkCutter = 0;
|
||||
MinEventTimeout = 30;
|
||||
MinUserInactivity = 300;
|
||||
NextWakeupTime = 0;
|
||||
@@ -639,8 +641,10 @@
|
||||
else if (!strcasecmp(Name, "FontSmlSize")) FontSmlSize = atoi(Value);
|
||||
else if (!strcasecmp(Name, "FontFixSize")) FontFixSize = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MaxVideoFileSize")) MaxVideoFileSize = atoi(Value);
|
||||
+ else if (!strcasecmp(Name, "MaxRecordingSize")) MaxRecordingSize = atoi(Value);
|
||||
else if (!strcasecmp(Name, "SplitEditedFiles")) SplitEditedFiles = atoi(Value);
|
||||
else if (!strcasecmp(Name, "DelTimeshiftRec")) DelTimeshiftRec = atoi(Value);
|
||||
+ else if (!strcasecmp(Name, "HardLinkCutter")) HardLinkCutter = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MinEventTimeout")) MinEventTimeout = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MinUserInactivity")) MinUserInactivity = atoi(Value);
|
||||
else if (!strcasecmp(Name, "NextWakeupTime")) NextWakeupTime = atoi(Value);
|
||||
@@ -736,8 +740,10 @@
|
||||
Store("FontSmlSize", FontSmlSize);
|
||||
Store("FontFixSize", FontFixSize);
|
||||
Store("MaxVideoFileSize", MaxVideoFileSize);
|
||||
+ Store("MaxRecordingSize", MaxRecordingSize);
|
||||
Store("SplitEditedFiles", SplitEditedFiles);
|
||||
Store("DelTimeshiftRec", DelTimeshiftRec);
|
||||
+ Store("HardLinkCutter", HardLinkCutter);
|
||||
Store("MinEventTimeout", MinEventTimeout);
|
||||
Store("MinUserInactivity", MinUserInactivity);
|
||||
Store("NextWakeupTime", NextWakeupTime);
|
||||
diff -Naur vdr-1.7.27/config.h vdr-1.7.27-hlcutter/config.h
|
||||
--- vdr-1.7.27/config.h 2012-03-11 11:41:44.000000000 +0100
|
||||
+++ vdr-1.7.27-hlcutter/config.h 2012-03-31 13:25:56.000000000 +0200
|
||||
@@ -299,8 +299,10 @@
|
||||
int FontSmlSize;
|
||||
int FontFixSize;
|
||||
int MaxVideoFileSize;
|
||||
+ int MaxRecordingSize;
|
||||
int SplitEditedFiles;
|
||||
int DelTimeshiftRec;
|
||||
+ int HardLinkCutter;
|
||||
int MinEventTimeout, MinUserInactivity;
|
||||
time_t NextWakeupTime;
|
||||
int MultiSpeedMode;
|
||||
diff -Naur vdr-1.7.27/cutter.c vdr-1.7.27-hlcutter/cutter.c
|
||||
--- vdr-1.7.27/cutter.c 2012-02-16 13:08:39.000000000 +0100
|
||||
+++ vdr-1.7.27-hlcutter/cutter.c 2012-03-31 13:26:51.000000000 +0200
|
||||
@@ -80,6 +80,7 @@
|
||||
Mark = fromMarks.Next(Mark);
|
||||
off_t FileSize = 0;
|
||||
int CurrentFileNumber = 0;
|
||||
+ bool SkipThisSourceFile = false;
|
||||
int LastIFrame = 0;
|
||||
toMarks.Add(0);
|
||||
toMarks.Save();
|
||||
@@ -98,13 +99,93 @@
|
||||
|
||||
// Read one frame:
|
||||
|
||||
- if (fromIndex->Get(Index++, &FileNumber, &FileOffset, &Independent, &Length)) {
|
||||
- if (FileNumber != CurrentFileNumber) {
|
||||
- fromFile = fromFileName->SetOffset(FileNumber, FileOffset);
|
||||
- if (fromFile)
|
||||
- fromFile->SetReadAhead(MEGABYTE(20));
|
||||
- CurrentFileNumber = FileNumber;
|
||||
- }
|
||||
+ if (!fromIndex->Get(Index++, &FileNumber, &FileOffset, &Independent, &Length)) {
|
||||
+ // Error, unless we're past last cut-in and there's no cut-out
|
||||
+ if (Mark || LastMark)
|
||||
+ error = "index";
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (FileNumber != CurrentFileNumber) {
|
||||
+ fromFile = fromFileName->SetOffset(FileNumber, FileOffset);
|
||||
+ if (fromFile)
|
||||
+ fromFile->SetReadAhead(MEGABYTE(20));
|
||||
+ CurrentFileNumber = FileNumber;
|
||||
+ if (SkipThisSourceFile) {
|
||||
+ // At end of fast forward: Always skip to next file
|
||||
+ toFile = toFileName->NextFile();
|
||||
+ if (!toFile) {
|
||||
+ error = "toFile 4";
|
||||
+ break;
|
||||
+ }
|
||||
+ FileSize = 0;
|
||||
+ SkipThisSourceFile = false;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ if (Setup.HardLinkCutter && FileOffset == 0) {
|
||||
+ // We are at the beginning of a new source file.
|
||||
+ // Do we need to copy the whole file?
|
||||
+
|
||||
+ // if !Mark && LastMark, then we're past the last cut-out and continue to next I-frame
|
||||
+ // if !Mark && !LastMark, then there's just a cut-in, but no cut-out
|
||||
+ // if Mark, then we're between a cut-in and a cut-out
|
||||
+
|
||||
+ uint16_t MarkFileNumber;
|
||||
+ off_t MarkFileOffset;
|
||||
+ // Get file number of next cut mark
|
||||
+ if (!Mark && !LastMark
|
||||
+ || Mark
|
||||
+ && fromIndex->Get(Mark->Position(), &MarkFileNumber, &MarkFileOffset)
|
||||
+ && (MarkFileNumber != CurrentFileNumber)) {
|
||||
+ // The current source file will be copied completely.
|
||||
+ // Start new output file unless we did that already
|
||||
+ if (FileSize != 0) {
|
||||
+ toFile = toFileName->NextFile();
|
||||
+ if (!toFile) {
|
||||
+ error = "toFile 3";
|
||||
+ break;
|
||||
+ }
|
||||
+ FileSize = 0;
|
||||
+ }
|
||||
+
|
||||
+ // Safety check that file has zero size
|
||||
+ struct stat buf;
|
||||
+ if (stat(toFileName->Name(), &buf) == 0) {
|
||||
+ if (buf.st_size != 0) {
|
||||
+ esyslog("cCuttingThread: File %s exists and has nonzero size", toFileName->Name());
|
||||
+ error = "nonzero file exist";
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ else if (errno != ENOENT) {
|
||||
+ esyslog("cCuttingThread: stat failed on %s", toFileName->Name());
|
||||
+ error = "stat";
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ // Clean the existing 0-byte file
|
||||
+ toFileName->Close();
|
||||
+ cString ActualToFileName(ReadLink(toFileName->Name()), true);
|
||||
+ unlink(ActualToFileName);
|
||||
+ unlink(toFileName->Name());
|
||||
+
|
||||
+ // Try to create a hard link
|
||||
+ if (HardLinkVideoFile(fromFileName->Name(), toFileName->Name())) {
|
||||
+ // Success. Skip all data transfer for this file
|
||||
+ SkipThisSourceFile = true;
|
||||
+ cutIn = false;
|
||||
+ toFile = NULL; // was deleted by toFileName->Close()
|
||||
+ }
|
||||
+ else {
|
||||
+ // Fallback: Re-open the file if necessary
|
||||
+ toFile = toFileName->Open();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!SkipThisSourceFile) {
|
||||
if (fromFile) {
|
||||
int len = ReadFrame(fromFile, buffer, Length, sizeof(buffer));
|
||||
if (len < 0) {
|
||||
@@ -121,19 +202,12 @@
|
||||
break;
|
||||
}
|
||||
}
|
||||
- else {
|
||||
- // Error, unless we're past the last cut-in and there's no cut-out
|
||||
- if (Mark || LastMark)
|
||||
- error = "index";
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
// Write one frame:
|
||||
|
||||
if (Independent) { // every file shall start with an independent frame
|
||||
if (LastMark) // edited version shall end before next I-frame
|
||||
break;
|
||||
- if (FileSize > maxVideoFileSize) {
|
||||
+ if (!SkipThisSourceFile && FileSize > toFileName->MaxFileSize()) {
|
||||
toFile = toFileName->NextFile();
|
||||
if (!toFile) {
|
||||
error = "toFile 1";
|
||||
@@ -143,7 +217,7 @@
|
||||
}
|
||||
CheckForSeamlessStream = false;
|
||||
}
|
||||
- if (cutIn) {
|
||||
+ if (!SkipThisSourceFile && cutIn) {
|
||||
if (isPesRecording)
|
||||
cRemux::SetBrokenLink(buffer, Length);
|
||||
else
|
||||
@@ -151,7 +225,7 @@
|
||||
cutIn = false;
|
||||
}
|
||||
}
|
||||
- if (toFile->Write(buffer, Length) < 0) {
|
||||
+ if (!SkipThisSourceFile && toFile->Write(buffer, Length) < 0) {
|
||||
error = "safe_write";
|
||||
break;
|
||||
}
|
||||
@@ -186,7 +260,7 @@
|
||||
}
|
||||
}
|
||||
else
|
||||
- LastMark = true;
|
||||
+ LastMark = true; // After last cut-out: Write on until next I-frame, then exit
|
||||
}
|
||||
}
|
||||
Recordings.TouchUpdate();
|
||||
diff -Naur vdr-1.7.27/menu.c vdr-1.7.27-hlcutter/menu.c
|
||||
--- vdr-1.7.27/menu.c 2012-03-13 14:14:38.000000000 +0100
|
||||
+++ vdr-1.7.27-hlcutter/menu.c 2012-03-31 13:25:56.000000000 +0200
|
||||
@@ -3116,8 +3116,10 @@
|
||||
Add(new cMenuEditStrItem( tr("Setup.Recording$Name instant recording"), data.NameInstantRecord, sizeof(data.NameInstantRecord)));
|
||||
Add(new cMenuEditIntItem( tr("Setup.Recording$Instant rec. time (min)"), &data.InstantRecordTime, 1, MAXINSTANTRECTIME));
|
||||
Add(new cMenuEditIntItem( tr("Setup.Recording$Max. video file size (MB)"), &data.MaxVideoFileSize, MINVIDEOFILESIZE, MAXVIDEOFILESIZETS));
|
||||
+ Add(new cMenuEditIntItem( tr("Setup.Recording$Max. recording size (GB)"), &data.MaxRecordingSize, MINRECORDINGSIZE, MAXRECORDINGSIZE));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.Recording$Split edited files"), &data.SplitEditedFiles));
|
||||
Add(new cMenuEditStraItem(tr("Setup.Recording$Delete timeshift recording"),&data.DelTimeshiftRec, 3, delTimeshiftRecTexts));
|
||||
+ Add(new cMenuEditBoolItem(tr("Setup.Recording$Hard Link Cutter"), &data.HardLinkCutter));
|
||||
}
|
||||
|
||||
// --- cMenuSetupReplay ------------------------------------------------------
|
||||
diff -Naur vdr-1.7.27/po/de_DE.po vdr-1.7.27-hlcutter/po/de_DE.po
|
||||
--- vdr-1.7.27/po/de_DE.po 2012-03-11 11:44:44.000000000 +0100
|
||||
+++ vdr-1.7.27-hlcutter/po/de_DE.po 2012-03-31 13:36:31.000000000 +0200
|
||||
@@ -1071,12 +1071,18 @@
|
||||
msgid "Setup.Recording$Max. video file size (MB)"
|
||||
msgstr "Max. Videodateigröße (MB)"
|
||||
|
||||
+msgid "Setup.Recording$Max. recording size (GB)"
|
||||
+msgstr "Max. Aufnahmegröße (GB)"
|
||||
+
|
||||
msgid "Setup.Recording$Split edited files"
|
||||
msgstr "Editierte Dateien aufteilen"
|
||||
|
||||
msgid "Setup.Recording$Delete timeshift recording"
|
||||
msgstr "Zeitversetzte Aufnahme löschen"
|
||||
|
||||
+msgid "Setup.Recording$Hard Link Cutter"
|
||||
+msgstr "Hard Link Cutter"
|
||||
+
|
||||
msgid "Replay"
|
||||
msgstr "Wiedergabe"
|
||||
|
||||
diff -Naur vdr-1.7.27/po/fi_FI.po vdr-1.7.27-hlcutter/po/fi_FI.po
|
||||
--- vdr-1.7.27/po/fi_FI.po 2012-03-11 11:44:43.000000000 +0100
|
||||
+++ vdr-1.7.27-hlcutter/po/fi_FI.po 2012-03-31 13:39:33.000000000 +0200
|
||||
@@ -1074,12 +1074,18 @@
|
||||
msgid "Setup.Recording$Max. video file size (MB)"
|
||||
msgstr "Suurin tiedostokoko (Mt)"
|
||||
|
||||
+msgid "Setup.Recording$Max. recording size (GB)"
|
||||
+msgstr "Suurin tallennekoko (Gt)"
|
||||
+
|
||||
msgid "Setup.Recording$Split edited files"
|
||||
msgstr "Jaottele muokatut tallenteet"
|
||||
|
||||
msgid "Setup.Recording$Delete timeshift recording"
|
||||
msgstr "Poista ajansiirtotallenne"
|
||||
|
||||
+msgid "Setup.Recording$Hard Link Cutter"
|
||||
+msgstr "Käytä kovia linkkejä muokkauksessa"
|
||||
+
|
||||
msgid "Replay"
|
||||
msgstr "Toisto"
|
||||
|
||||
diff -Naur vdr-1.7.27/README-HLCUTTER vdr-1.7.27-hlcutter/README-HLCUTTER
|
||||
--- vdr-1.7.27/README-HLCUTTER 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ vdr-1.7.27-hlcutter/README-HLCUTTER 2012-03-31 13:40:55.000000000 +0200
|
||||
@@ -0,0 +1,128 @@
|
||||
+
|
||||
+ VDR-HLCUTTER README
|
||||
+
|
||||
+
|
||||
+Written by: Udo Richter
|
||||
+Available at: http://www.udo-richter.de/vdr/patches.html#hlcutter
|
||||
+ http://www.udo-richter.de/vdr/patches.en.html#hlcutter
|
||||
+Contact: udo_richter@gmx.de
|
||||
+
|
||||
+
|
||||
+
|
||||
+About
|
||||
+-----
|
||||
+
|
||||
+The hard link cutter patch changes the recording editing algorithms of VDR to
|
||||
+use filesystem hard links to 'copy' recording files whenever possible to speed
|
||||
+up editing recordings noticeably.
|
||||
+
|
||||
+The patch has matured to be quite stable, at least I'm using it without issues.
|
||||
+Nevertheless the patch is still in development and should be used with caution.
|
||||
+The patch is EXPERIMENTAL for multiple /videoxx folders. The safety checks
|
||||
+should prevent data loss, but you should always carefully check the results.
|
||||
+
|
||||
+While editing a recording, the patch searches for any 00x.vdr files that don't
|
||||
+contain editing marks and would normally be copied 1:1 unmodified to the edited
|
||||
+recording. In this case the current target 00x.vdr file will be aborted, and
|
||||
+the cutter process attempts to duplicate the source file as a hard link, so
|
||||
+that both files share the same disk space. If this succeeds, the editing
|
||||
+process fast-forwards through the duplicated file and continues normally
|
||||
+beginning with the next source file. If hard linking fails, the cutter process
|
||||
+continues with plain old copying. (but does not take up the aborted last file.)
|
||||
+
|
||||
+After editing, the un-edited recording can be deleted as usual, the hard linked
|
||||
+copies will continue to exist as the only remaining copy.
|
||||
+
|
||||
+To be effective, the default 'Max. video file size (MB)' should be lowered.
|
||||
+The patch lowers the smallest possible file size to 1mb. Since VDR only
|
||||
+supports up to 255 files, this would limit the recording size to 255Mb or
|
||||
+10 minutes, in other words: This setting is insane!
|
||||
+
|
||||
+To make sure that the 255 file limit will not be reached, the patch also
|
||||
+introduces "Max. recording size (GB)" with a default of 100Gb (66 hours), and
|
||||
+increases the file size to 2000Mb early enough, so that 100Gb-recordings will
|
||||
+fit into the 255 files.
|
||||
+
|
||||
+Picking the right parameters can be tricky. The smaller the file size, the
|
||||
+faster the editing process works. However, with a small file size, long
|
||||
+recordings will fall back to 2000Mb files soon, that are slow on editing again.
|
||||
+
|
||||
+Here are some examples:
|
||||
+
|
||||
+Max file size: 100Gb 100Gb 100Gb 100Gb 100Gb 100Gb 100Gb
|
||||
+Max recording size: 1Mb 10Mb 20Mb 30Mb 40Mb 50Mb 100Mb
|
||||
+
|
||||
+Small files: 1-203 1-204 1-205 1-206 1-207 1-209 1-214
|
||||
+ GBytes: 0.2 2.0 4.0 6.0 8.1 10.2 20.9
|
||||
+ Hours: 0.13 1.3 2.65 4 5.4 6.8 13.9
|
||||
+
|
||||
+Big (2000mb) files: 204-255 204-255 206-255 207-255 208-255 210-255 215-255
|
||||
+ GBytes: 101.5 99.6 97.7 95.7 93.8 89.8 80.1
|
||||
+ Hours: 67 66 65 63 62 60 53
|
||||
+
|
||||
+A recording limit of 100Gb keeps plenty of reserve without blocking too much
|
||||
+file numbers. And with a file size of 30-40Mb, recordings of 4-5 hours fit into
|
||||
+small files completely. (depends on bit rate of course)
|
||||
+
|
||||
+
|
||||
+
|
||||
+The patch must be enabled in Setup-> Recordings-> Hard Link Cutter. When
|
||||
+disabled, the cutter process behaves identical to VDR's default cutter.
|
||||
+
|
||||
+There's a //#define HARDLINK_TEST_ONLY in the videodir.c file that enables a
|
||||
+test-mode that hard-links 00x.vdr_ files only, and continues the classic
|
||||
+editing. The resulting 00x.vdr and 00x.vdr_ files should be identical. If you
|
||||
+delete the un-edited recording, don't forget to delete the *.vdr_ files too,
|
||||
+they will now eat real disk space.
|
||||
+
|
||||
+Note: 'du' displays the disk space of hard links only on first appearance, and
|
||||
+usually you will see a noticeably smaller size on the edited recording.
|
||||
+
|
||||
+
|
||||
+History
|
||||
+-------
|
||||
+
|
||||
+Version 0.2.3
|
||||
+ Fix: Compatible to VDR-1.7.27+ thx to Ville Skyttä
|
||||
+ New: Add German translation
|
||||
+ New: Add Finnish translation, thx to Ville Skyttä
|
||||
+
|
||||
+Version 0.2.2
|
||||
+ Fix: Adapt to GCC-4.4, thx to Ville Skyttä
|
||||
+
|
||||
+Version 0.2.1
|
||||
+ New: Support for TS recordings with up to 65535 files and up to 1TB per file
|
||||
+
|
||||
+Version 0.2.0
|
||||
+ New: Support for multiple /videoXX recording folders, using advanced searching
|
||||
+ for matching file systems where a hard link can be created.
|
||||
+ Also supports deep mounted file systems.
|
||||
+ Fix: Do not fail if last mark is a cut-in. (Again.)
|
||||
+
|
||||
+Version 0.1.4
|
||||
+ New: Dynamic increase of file size before running out of xxx.vdr files
|
||||
+ Fix: Last edit mark is not a cut-out
|
||||
+ Fix: Write error if link-copied file is smaller than allowed file size
|
||||
+ Fix: Broken index/marks if cut-in is at the start of a new file
|
||||
+ Fix: Clear dangling pointer to free'd cUnbufferedFile,
|
||||
+ thx to Matthias Schwarzott
|
||||
+
|
||||
+Version 0.1.0
|
||||
+ Initial release
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
+Future plans
|
||||
+------------
|
||||
+
|
||||
+Since original and edited copy share disk space, free space is wrong if one of
|
||||
+them is moved to *.del. Free space should only count files with hard link
|
||||
+count = 1. This still goes wrong if all copies get deleted.
|
||||
+
|
||||
+
|
||||
+For more safety, the hard-linked files may be made read-only, as modifications
|
||||
+to one copy will affect the other copy too. (except deleting, of course)
|
||||
+
|
||||
+
|
||||
+SetBrokenLink may get lost on rare cases, this needs some more thoughts.
|
||||
diff -Naur vdr-1.7.27/recorder.c vdr-1.7.27-hlcutter/recorder.c
|
||||
--- vdr-1.7.27/recorder.c 2011-09-04 11:26:44.000000000 +0200
|
||||
+++ vdr-1.7.27-hlcutter/recorder.c 2012-03-31 13:25:56.000000000 +0200
|
||||
@@ -89,7 +89,7 @@
|
||||
bool cRecorder::NextFile(void)
|
||||
{
|
||||
if (recordFile && frameDetector->IndependentFrame()) { // every file shall start with an independent frame
|
||||
- if (fileSize > MEGABYTE(off_t(Setup.MaxVideoFileSize)) || RunningLowOnDiskSpace()) {
|
||||
+ if (fileSize > fileName->MaxFileSize() || RunningLowOnDiskSpace()) {
|
||||
recordFile = fileName->NextFile();
|
||||
fileSize = 0;
|
||||
}
|
||||
diff -Naur vdr-1.7.27/recording.c vdr-1.7.27-hlcutter/recording.c
|
||||
--- vdr-1.7.27/recording.c 2012-03-13 14:17:57.000000000 +0100
|
||||
+++ vdr-1.7.27-hlcutter/recording.c 2012-03-31 13:25:56.000000000 +0200
|
||||
@@ -2064,6 +2064,20 @@
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+off_t cFileName::MaxFileSize() {
|
||||
+ const int maxVideoFileSize = isPesRecording ? MAXVIDEOFILESIZEPES : MAXVIDEOFILESIZETS;
|
||||
+ const int setupMaxVideoFileSize = min(maxVideoFileSize, Setup.MaxVideoFileSize);
|
||||
+ const int maxFileNumber = isPesRecording ? 255 : 65535;
|
||||
+
|
||||
+ const off_t smallFiles = (maxFileNumber * off_t(maxVideoFileSize) - 1024 * Setup.MaxRecordingSize)
|
||||
+ / max(maxVideoFileSize - setupMaxVideoFileSize, 1);
|
||||
+
|
||||
+ if (fileNumber <= smallFiles)
|
||||
+ return MEGABYTE(off_t(setupMaxVideoFileSize));
|
||||
+
|
||||
+ return MEGABYTE(off_t(maxVideoFileSize));
|
||||
+}
|
||||
+
|
||||
cUnbufferedFile *cFileName::NextFile(void)
|
||||
{
|
||||
return SetOffset(fileNumber + 1);
|
||||
diff -Naur vdr-1.7.27/recording.h vdr-1.7.27-hlcutter/recording.h
|
||||
--- vdr-1.7.27/recording.h 2012-03-13 13:41:05.000000000 +0100
|
||||
+++ vdr-1.7.27-hlcutter/recording.h 2012-03-31 13:25:56.000000000 +0200
|
||||
@@ -264,9 +264,17 @@
|
||||
// before the next independent frame, to have a complete Group Of Pictures):
|
||||
#define MAXVIDEOFILESIZETS 1048570 // MB
|
||||
#define MAXVIDEOFILESIZEPES 2000 // MB
|
||||
-#define MINVIDEOFILESIZE 100 // MB
|
||||
+#define MINVIDEOFILESIZE 1 // MB
|
||||
#define MAXVIDEOFILESIZEDEFAULT MAXVIDEOFILESIZEPES
|
||||
|
||||
+#define MINRECORDINGSIZE 25 // GB
|
||||
+#define MAXRECORDINGSIZE 500 // GB
|
||||
+#define DEFAULTRECORDINGSIZE 100 // GB
|
||||
+// Dynamic recording size:
|
||||
+// Keep recording file size at Setup.MaxVideoFileSize for as long as possible,
|
||||
+// but switch to MAXVIDEOFILESIZE early enough, so that Setup.MaxRecordingSize
|
||||
+// will be reached, before recording to file 65535.vdr
|
||||
+
|
||||
struct tIndexTs;
|
||||
class cIndexFileGenerator;
|
||||
|
||||
@@ -319,6 +327,8 @@
|
||||
cUnbufferedFile *Open(void);
|
||||
void Close(void);
|
||||
cUnbufferedFile *SetOffset(int Number, off_t Offset = 0); // yes, Number is int for easier internal calculating
|
||||
+ off_t MaxFileSize();
|
||||
+ // Dynamic file size for this file
|
||||
cUnbufferedFile *NextFile(void);
|
||||
};
|
||||
|
||||
diff -Naur vdr-1.7.27/videodir.c vdr-1.7.27-hlcutter/videodir.c
|
||||
--- vdr-1.7.27/videodir.c 2008-02-16 14:00:03.000000000 +0100
|
||||
+++ vdr-1.7.27-hlcutter/videodir.c 2012-03-31 13:25:56.000000000 +0200
|
||||
@@ -19,6 +19,9 @@
|
||||
#include "recording.h"
|
||||
#include "tools.h"
|
||||
|
||||
+
|
||||
+//#define HARDLINK_TEST_ONLY
|
||||
+
|
||||
const char *VideoDirectory = VIDEODIR;
|
||||
|
||||
class cVideoDirectory {
|
||||
@@ -168,6 +171,120 @@
|
||||
return RemoveFileOrDir(FileName, true);
|
||||
}
|
||||
|
||||
+static bool StatNearestDir(const char *FileName, struct stat *Stat)
|
||||
+{
|
||||
+ cString Name(FileName);
|
||||
+ char *p;
|
||||
+ while ((p = strrchr((char*)(const char*)Name + 1, '/')) != NULL) {
|
||||
+ *p = 0; // truncate at last '/'
|
||||
+ if (stat(Name, Stat) == 0) {
|
||||
+ isyslog("StatNearestDir: Stating %s", (const char*)Name);
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+bool HardLinkVideoFile(const char *OldName, const char *NewName)
|
||||
+{
|
||||
+ // Incoming name must be in base video directory:
|
||||
+ if (strstr(OldName, VideoDirectory) != OldName) {
|
||||
+ esyslog("ERROR: %s not in %s", OldName, VideoDirectory);
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (strstr(NewName, VideoDirectory) != NewName) {
|
||||
+ esyslog("ERROR: %s not in %s", NewName, VideoDirectory);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ const char *ActualNewName = NewName;
|
||||
+ cString ActualOldName(ReadLink(OldName), true);
|
||||
+
|
||||
+ // Some safety checks:
|
||||
+ struct stat StatOldName;
|
||||
+ if (lstat(ActualOldName, &StatOldName) == 0) {
|
||||
+ if (S_ISLNK(StatOldName.st_mode)) {
|
||||
+ esyslog("HardLinkVideoFile: Failed to resolve symbolic link %s", (const char*)ActualOldName);
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ else {
|
||||
+ esyslog("HardLinkVideoFile: lstat failed on %s", (const char*)ActualOldName);
|
||||
+ return false;
|
||||
+ }
|
||||
+ isyslog("HardLinkVideoFile: %s is on %i", (const char*)ActualOldName, (int)StatOldName.st_dev);
|
||||
+
|
||||
+ // Find the video directory where ActualOldName is located
|
||||
+
|
||||
+ cVideoDirectory Dir;
|
||||
+ struct stat StatDir;
|
||||
+ if (!StatNearestDir(NewName, &StatDir)) {
|
||||
+ esyslog("HardLinkVideoFile: stat failed on %s", NewName);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ isyslog("HardLinkVideoFile: %s is on %i", NewName, (int)StatDir.st_dev);
|
||||
+ if (StatDir.st_dev != StatOldName.st_dev) {
|
||||
+ // Not yet found.
|
||||
+
|
||||
+ if (!Dir.IsDistributed()) {
|
||||
+ esyslog("HardLinkVideoFile: No matching video folder to hard link %s", (const char*)ActualOldName);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // Search in video01 and upwards
|
||||
+ bool found = false;
|
||||
+ while (Dir.Next()) {
|
||||
+ Dir.Store();
|
||||
+ const char *TmpNewName = Dir.Adjust(NewName);
|
||||
+ if (StatNearestDir(TmpNewName, &StatDir) && StatDir.st_dev == StatOldName.st_dev) {
|
||||
+ isyslog("HardLinkVideoFile: %s is on %i (match)", TmpNewName, (int)StatDir.st_dev);
|
||||
+ ActualNewName = TmpNewName;
|
||||
+ found = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ isyslog("HardLinkVideoFile: %s is on %i", TmpNewName, (int)StatDir.st_dev);
|
||||
+ }
|
||||
+ if (ActualNewName == NewName) {
|
||||
+ esyslog("HardLinkVideoFile: No matching video folder to hard link %s", (const char*)ActualOldName);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // Looking good, we have a match. Create necessary folders.
|
||||
+ if (!MakeDirs(ActualNewName, false))
|
||||
+ return false;
|
||||
+ // There's no guarantee that the directory of ActualNewName
|
||||
+ // is on the same device as the dir that StatNearestDir found.
|
||||
+ // But worst case is that the link fails.
|
||||
+ }
|
||||
+
|
||||
+#ifdef HARDLINK_TEST_ONLY
|
||||
+ // Do the hard link to *.vdr_ for testing only
|
||||
+ char *name = NULL;
|
||||
+ asprintf(&name, "%s_",ActualNewName);
|
||||
+ link(ActualOldName, name);
|
||||
+ free(name);
|
||||
+ return false;
|
||||
+#endif // HARDLINK_TEST_ONLY
|
||||
+
|
||||
+ // Try creating the hard link
|
||||
+ if (link(ActualOldName, ActualNewName) != 0) {
|
||||
+ // Failed to hard link. Maybe not allowed on file system.
|
||||
+ LOG_ERROR_STR(ActualNewName);
|
||||
+ isyslog("HardLinkVideoFile: failed to hard link from %s to %s", (const char*)ActualOldName, ActualNewName);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (ActualNewName != NewName) {
|
||||
+ // video01 and up. Do the remaining symlink
|
||||
+ if (symlink(ActualNewName, NewName) < 0) {
|
||||
+ LOG_ERROR_STR(NewName);
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
bool VideoFileSpaceAvailable(int SizeMB)
|
||||
{
|
||||
cVideoDirectory Dir;
|
||||
diff -Naur vdr-1.7.27/videodir.h vdr-1.7.27-hlcutter/videodir.h
|
||||
--- vdr-1.7.27/videodir.h 2008-02-16 13:53:11.000000000 +0100
|
||||
+++ vdr-1.7.27-hlcutter/videodir.h 2012-03-31 13:25:56.000000000 +0200
|
||||
@@ -19,6 +19,7 @@
|
||||
int CloseVideoFile(cUnbufferedFile *File);
|
||||
bool RenameVideoFile(const char *OldName, const char *NewName);
|
||||
bool RemoveVideoFile(const char *FileName);
|
||||
+bool HardLinkVideoFile(const char *OldName, const char *NewName);
|
||||
bool VideoFileSpaceAvailable(int SizeMB);
|
||||
int VideoDiskSpace(int *FreeMB = NULL, int *UsedMB = NULL); // returns the used disk space in percent
|
||||
cString PrefixVideoFileName(const char *FileName, char Prefix);
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
diff -up vdr-1.7.41/epg2html~ vdr-1.7.41/epg2html
|
||||
--- vdr-1.7.41/epg2html~ 2013-03-04 15:02:20.000000000 +0200
|
||||
+++ vdr-1.7.41/epg2html 2013-03-16 19:08:17.467701640 +0200
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
# A simple EPG to HTML converter
|
||||
#
|
||||
-# Converts the EPG data written by 'vdr' into the file /video/epg.data
|
||||
+# Converts the EPG data written by 'vdr' into the file __CACHEDIR__/epg.data
|
||||
# into a simple HTML programme listing, consisting of one file per channel
|
||||
# plus an 'index.htm' file. All output files are written into the current
|
||||
# directory.
|
||||
#
|
||||
-# Usage: epg2html < /video/epg.data
|
||||
+# Usage: epg2html < __CACHEDIR__/epg.data
|
||||
#
|
||||
# See the main source file 'vdr.c' for copyright information and
|
||||
# how to reach the author.
|
||||
diff -up vdr-1.7.41/newplugin~ vdr-1.7.41/newplugin
|
||||
--- vdr-1.7.41/newplugin~ 2013-01-12 15:46:00.000000000 +0200
|
||||
+++ vdr-1.7.41/newplugin 2013-03-16 19:08:18.140713300 +0200
|
||||
@@ -24,7 +24,7 @@ $PLUGIN_VERSION = "0.0.1";
|
||||
$PLUGIN_DESCRIPTION = "Enter description for '$PLUGIN_NAME' plugin";
|
||||
$PLUGIN_MAINENTRY = $PLUGIN_CLASS;
|
||||
|
||||
-$PLUGINS_SRC = "PLUGINS/src";
|
||||
+$PLUGINS_SRC = ".";
|
||||
|
||||
$README = qq
|
||||
{This is a "plugin" for the Video Disk Recorder (VDR).
|
||||
diff -up vdr-1.7.41/vdr.1~ vdr-1.7.41/vdr.1
|
||||
--- vdr-1.7.41/vdr.1~ 2013-03-15 12:44:54.000000000 +0200
|
||||
+++ vdr-1.7.41/vdr.1 2013-03-16 19:08:16.621686914 +0200
|
||||
@@ -51,7 +51,7 @@ Save cache files in \fIdir\fR
|
||||
.TP
|
||||
.BI \-c\ dir ,\ \-\-config= dir
|
||||
Read config files from directory \fIdir\fR
|
||||
-(default is to read them from the video directory).
|
||||
+(default is to read them from __CONFIGDIR__).
|
||||
.TP
|
||||
.B \-d, \-\-daemon
|
||||
Run in daemon mode (implies \-\-no\-kbd).
|
||||
@@ -130,7 +130,7 @@ If logging should be done to LOG_LOCAL\f
|
||||
LOG_USER, add '.n' to LEVEL, as in 3.7 (n=0..7).
|
||||
.TP
|
||||
.BI \-L\ dir ,\ \-\-lib= dir
|
||||
-Search for plugins in directory \fIdir\fR (default is ./PLUGINS/lib).
|
||||
+Search for plugins in directory \fIdir\fR (default is __PLUGINDIR__).
|
||||
There can be several \fB\-L\fR options with different \fIdir\fR values.
|
||||
Each of them will apply to the \fB\-P\fR options following it.
|
||||
.TP
|
||||
@@ -205,7 +205,7 @@ For backwards compatibility (same as \-\
|
||||
.TP
|
||||
.BI \-v\ dir ,\ \-\-video= dir
|
||||
Use \fIdir\fR as video directory.
|
||||
-The default is \fI/video\fR.
|
||||
+The default is \fI__VIDEODIR__\fR.
|
||||
.TP
|
||||
.B \-V, \-\-version
|
||||
Print version information and exit.
|
||||
diff -up vdr-1.7.41/vdr.5~ vdr-1.7.41/vdr.5
|
||||
--- vdr-1.7.41/vdr.5~ 2013-03-11 15:17:12.000000000 +0200
|
||||
+++ vdr-1.7.41/vdr.5 2013-03-16 19:08:18.908726601 +0200
|
||||
@@ -711,7 +711,7 @@ The file \fIsetup.conf\fR contains the b
|
||||
Each line contains one option in the format "Name = Value".
|
||||
See the MANUAL file for a description of the available options.
|
||||
.SS THEMES
|
||||
-The files \fIthemes/<skin>\-<theme>.theme\fR in the config directory contain the
|
||||
+The files \fI__VARDIR__/themes/<skin>\-<theme>.theme\fR contain the
|
||||
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.
|
||||
diff -up vdr-1.7.41/vdr.c~ vdr-1.7.41/vdr.c
|
||||
--- vdr-1.7.41/vdr.c~ 2013-03-15 12:44:54.000000000 +0200
|
||||
+++ vdr-1.7.41/vdr.c 2013-03-16 19:08:15.861673670 +0200
|
||||
@@ -673,7 +673,7 @@ int main(int argc, char *argv[])
|
||||
if (!ResourceDirectory)
|
||||
ResourceDirectory = DEFAULTRESDIR;
|
||||
cPlugin::SetResourceDirectory(ResourceDirectory);
|
||||
- cThemes::SetThemesDirectory(AddDirectory(ConfigDirectory, "themes"));
|
||||
+ cThemes::SetThemesDirectory("__VARDIR__/themes");
|
||||
|
||||
// Configuration data:
|
||||
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
diff -up vdr-2.0.4/config.h~ vdr-2.0.4/config.h
|
||||
--- vdr-2.0.4/config.h~ 2013-09-07 13:25:10.000000000 +0300
|
||||
+++ vdr-2.0.4/config.h 2013-10-23 19:43:24.731445495 +0300
|
||||
@@ -47,6 +47,10 @@
|
||||
#define TIMERMACRO_TITLE "TITLE"
|
||||
#define TIMERMACRO_EPISODE "EPISODE"
|
||||
|
||||
+// The MainMenuHook Patch's version number:
|
||||
+#define MAINMENUHOOKSVERSION "1.0.1"
|
||||
+#define MAINMENUHOOKSVERSNUM 10001 // Version * 10000 + Major * 100 + Minor
|
||||
+
|
||||
#define MINOSDWIDTH 480
|
||||
#define MAXOSDWIDTH 1920
|
||||
#define MINOSDHEIGHT 324
|
||||
diff -up vdr-2.0.4/menu.c~ vdr-2.0.4/menu.c
|
||||
--- vdr-2.0.4/menu.c~ 2013-10-16 12:46:24.000000000 +0300
|
||||
+++ vdr-2.0.4/menu.c 2013-10-23 19:43:24.275436244 +0300
|
||||
@@ -3377,15 +3377,31 @@ cMenuMain::cMenuMain(eOSState State, boo
|
||||
|
||||
// Initial submenus:
|
||||
|
||||
+ cOsdObject *menu = NULL;
|
||||
switch (State) {
|
||||
- case osSchedule: AddSubMenu(new cMenuSchedule); break;
|
||||
- case osChannels: AddSubMenu(new cMenuChannels); break;
|
||||
- case osTimers: AddSubMenu(new cMenuTimers); break;
|
||||
- case osRecordings: AddSubMenu(new cMenuRecordings(NULL, 0, OpenSubMenus)); break;
|
||||
- case osSetup: AddSubMenu(new cMenuSetup); break;
|
||||
- case osCommands: AddSubMenu(new cMenuCommands(tr("Commands"), &Commands)); break;
|
||||
+ case osSchedule:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu))
|
||||
+ menu = new cMenuSchedule;
|
||||
+ break;
|
||||
+ case osChannels:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu))
|
||||
+ menu = new cMenuChannels;
|
||||
+ break;
|
||||
+ case osTimers:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu))
|
||||
+ menu = new cMenuTimers;
|
||||
+ break;
|
||||
+ case osRecordings:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu))
|
||||
+ menu = new cMenuRecordings(NULL, 0, OpenSubMenus);
|
||||
+ break;
|
||||
+ case osSetup: menu = new cMenuSetup; break;
|
||||
+ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break;
|
||||
default: break;
|
||||
}
|
||||
+ if (menu)
|
||||
+ if (menu->IsMenu())
|
||||
+ AddSubMenu((cOsdMenu *) menu);
|
||||
}
|
||||
|
||||
cOsdObject *cMenuMain::PluginOsdObject(void)
|
||||
@@ -3493,13 +3509,34 @@ eOSState cMenuMain::ProcessKey(eKeys Key
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
HadSubMenu |= HasSubMenu();
|
||||
|
||||
+ cOsdObject *menu = NULL;
|
||||
switch (state) {
|
||||
- case osSchedule: return AddSubMenu(new cMenuSchedule);
|
||||
- case osChannels: return AddSubMenu(new cMenuChannels);
|
||||
- case osTimers: return AddSubMenu(new cMenuTimers);
|
||||
- case osRecordings: return AddSubMenu(new cMenuRecordings);
|
||||
- case osSetup: return AddSubMenu(new cMenuSetup);
|
||||
- case osCommands: return AddSubMenu(new cMenuCommands(tr("Commands"), &Commands));
|
||||
+ case osSchedule:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu))
|
||||
+ menu = new cMenuSchedule;
|
||||
+ else
|
||||
+ state = osContinue;
|
||||
+ break;
|
||||
+ case osChannels:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu))
|
||||
+ menu = new cMenuChannels;
|
||||
+ else
|
||||
+ state = osContinue;
|
||||
+ break;
|
||||
+ case osTimers:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu))
|
||||
+ menu = new cMenuTimers;
|
||||
+ else
|
||||
+ state = osContinue;
|
||||
+ break;
|
||||
+ case osRecordings:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu))
|
||||
+ menu = new cMenuRecordings;
|
||||
+ else
|
||||
+ state = osContinue;
|
||||
+ break;
|
||||
+ case osSetup: menu = new cMenuSetup; break;
|
||||
+ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break;
|
||||
case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) {
|
||||
cOsdItem *item = Get(Current());
|
||||
if (item) {
|
||||
@@ -3551,6 +3588,12 @@ eOSState cMenuMain::ProcessKey(eKeys Key
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
+ if (menu) {
|
||||
+ if (menu->IsMenu())
|
||||
+ return AddSubMenu((cOsdMenu *) menu);
|
||||
+ pluginOsdObject = menu;
|
||||
+ return osPlugin;
|
||||
+ }
|
||||
if (!HasSubMenu() && Update(HadSubMenu))
|
||||
Display();
|
||||
if (Key != kNone) {
|
||||
|
|
@ -1,621 +0,0 @@
|
|||
diff -Naur vdr-2.1.6/config.c vdr-2.1.6-naludump-0.1/config.c
|
||||
--- vdr-2.1.6/config.c 2013-08-31 14:41:28.000000000 +0200
|
||||
+++ vdr-2.1.6-naludump-0.1/config.c 2014-03-30 17:47:25.000000000 +0200
|
||||
@@ -462,6 +462,7 @@
|
||||
MaxVideoFileSize = MAXVIDEOFILESIZEDEFAULT;
|
||||
SplitEditedFiles = 0;
|
||||
DelTimeshiftRec = 0;
|
||||
+ DumpNaluFill = 0;
|
||||
MinEventTimeout = 30;
|
||||
MinUserInactivity = 300;
|
||||
NextWakeupTime = 0;
|
||||
@@ -673,6 +674,7 @@
|
||||
else if (!strcasecmp(Name, "MaxVideoFileSize")) MaxVideoFileSize = atoi(Value);
|
||||
else if (!strcasecmp(Name, "SplitEditedFiles")) SplitEditedFiles = atoi(Value);
|
||||
else if (!strcasecmp(Name, "DelTimeshiftRec")) DelTimeshiftRec = atoi(Value);
|
||||
+ else if (!strcasecmp(Name, "DumpNaluFill")) DumpNaluFill = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MinEventTimeout")) MinEventTimeout = atoi(Value);
|
||||
else if (!strcasecmp(Name, "MinUserInactivity")) MinUserInactivity = atoi(Value);
|
||||
else if (!strcasecmp(Name, "NextWakeupTime")) NextWakeupTime = atoi(Value);
|
||||
@@ -788,6 +790,7 @@
|
||||
Store("MaxVideoFileSize", MaxVideoFileSize);
|
||||
Store("SplitEditedFiles", SplitEditedFiles);
|
||||
Store("DelTimeshiftRec", DelTimeshiftRec);
|
||||
+ Store("DumpNaluFill", DumpNaluFill);
|
||||
Store("MinEventTimeout", MinEventTimeout);
|
||||
Store("MinUserInactivity", MinUserInactivity);
|
||||
Store("NextWakeupTime", NextWakeupTime);
|
||||
diff -Naur vdr-2.1.6/config.h vdr-2.1.6-naludump-0.1/config.h
|
||||
--- vdr-2.1.6/config.h 2014-02-25 11:00:23.000000000 +0100
|
||||
+++ vdr-2.1.6-naludump-0.1/config.h 2014-03-30 17:47:25.000000000 +0200
|
||||
@@ -326,6 +326,7 @@
|
||||
int MaxVideoFileSize;
|
||||
int SplitEditedFiles;
|
||||
int DelTimeshiftRec;
|
||||
+ int DumpNaluFill;
|
||||
int MinEventTimeout, MinUserInactivity;
|
||||
time_t NextWakeupTime;
|
||||
int MultiSpeedMode;
|
||||
diff -Naur vdr-2.1.6/menu.c vdr-2.1.6-naludump-0.1/menu.c
|
||||
--- vdr-2.1.6/menu.c 2014-03-16 11:38:31.000000000 +0100
|
||||
+++ vdr-2.1.6-naludump-0.1/menu.c 2014-03-30 17:47:25.000000000 +0200
|
||||
@@ -3547,6 +3547,7 @@
|
||||
Add(new cMenuEditIntItem( tr("Setup.Recording$Max. video file size (MB)"), &data.MaxVideoFileSize, MINVIDEOFILESIZE, MAXVIDEOFILESIZETS));
|
||||
Add(new cMenuEditBoolItem(tr("Setup.Recording$Split edited files"), &data.SplitEditedFiles));
|
||||
Add(new cMenuEditStraItem(tr("Setup.Recording$Delete timeshift recording"),&data.DelTimeshiftRec, 3, delTimeshiftRecTexts));
|
||||
+ Add(new cMenuEditBoolItem(tr("Setup.Recording$Dump NALU Fill data"), &data.DumpNaluFill));
|
||||
}
|
||||
|
||||
// --- cMenuSetupReplay ------------------------------------------------------
|
||||
diff -Naur vdr-2.1.6/recorder.c vdr-2.1.6-naludump-0.1/recorder.c
|
||||
--- vdr-2.1.6/recorder.c 2014-02-21 10:19:52.000000000 +0100
|
||||
+++ vdr-2.1.6-naludump-0.1/recorder.c 2014-03-30 17:47:25.000000000 +0200
|
||||
@@ -46,6 +46,14 @@
|
||||
Type = 0x06;
|
||||
}
|
||||
frameDetector = new cFrameDetector(Pid, Type);
|
||||
+ if ( Type == 0x1B // MPEG4 video
|
||||
+ && (Setup.DumpNaluFill ? (strstr(FileName, "NALUKEEP") == NULL) : (strstr(FileName, "NALUDUMP") != NULL))) { // MPEG4
|
||||
+ isyslog("Starting NALU fill dumper");
|
||||
+ naluStreamProcessor = new cNaluStreamProcessor();
|
||||
+ naluStreamProcessor->SetPid(Pid);
|
||||
+ }
|
||||
+ else
|
||||
+ naluStreamProcessor = NULL;
|
||||
index = NULL;
|
||||
fileSize = 0;
|
||||
lastDiskSpaceCheck = time(NULL);
|
||||
@@ -67,6 +75,12 @@
|
||||
cRecorder::~cRecorder()
|
||||
{
|
||||
Detach();
|
||||
+ if (naluStreamProcessor) {
|
||||
+ long long int TotalPackets = naluStreamProcessor->GetTotalPackets();
|
||||
+ long long int DroppedPackets = naluStreamProcessor->GetDroppedPackets();
|
||||
+ isyslog("NALU fill dumper: %lld of %lld packets dropped, %lli%%", DroppedPackets, TotalPackets, TotalPackets ? DroppedPackets*100/TotalPackets : 0);
|
||||
+ delete naluStreamProcessor;
|
||||
+ }
|
||||
delete index;
|
||||
delete fileName;
|
||||
delete frameDetector;
|
||||
@@ -157,11 +171,32 @@
|
||||
}
|
||||
t.Set(MAXBROKENTIMEOUT);
|
||||
}
|
||||
- if (recordFile->Write(b, Count) < 0) {
|
||||
- LOG_ERROR_STR(fileName->Name());
|
||||
- break;
|
||||
+ if (naluStreamProcessor) {
|
||||
+ naluStreamProcessor->PutBuffer(b, Count);
|
||||
+ bool Fail = false;
|
||||
+ while (true) {
|
||||
+ int OutLength = 0;
|
||||
+ uchar *OutData = naluStreamProcessor->GetBuffer(OutLength);
|
||||
+ if (!OutData || OutLength <= 0)
|
||||
+ break;
|
||||
+ if (recordFile->Write(OutData, OutLength) < 0) {
|
||||
+ LOG_ERROR_STR(fileName->Name());
|
||||
+ Fail = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ fileSize += OutLength;
|
||||
+ }
|
||||
+ if (Fail)
|
||||
+ break;
|
||||
+ }
|
||||
+ else {
|
||||
+ if (recordFile->Write(b, Count) < 0) {
|
||||
+ LOG_ERROR_STR(fileName->Name());
|
||||
+ break;
|
||||
+ }
|
||||
+ fileSize += Count;
|
||||
}
|
||||
- fileSize += Count;
|
||||
+
|
||||
}
|
||||
}
|
||||
ringBuffer->Del(Count);
|
||||
diff -Naur vdr-2.1.6/recorder.h vdr-2.1.6-naludump-0.1/recorder.h
|
||||
--- vdr-2.1.6/recorder.h 2010-12-27 12:17:04.000000000 +0100
|
||||
+++ vdr-2.1.6-naludump-0.1/recorder.h 2014-03-30 17:47:25.000000000 +0200
|
||||
@@ -21,6 +21,7 @@
|
||||
cRingBufferLinear *ringBuffer;
|
||||
cFrameDetector *frameDetector;
|
||||
cPatPmtGenerator patPmtGenerator;
|
||||
+ cNaluStreamProcessor *naluStreamProcessor;
|
||||
cFileName *fileName;
|
||||
cIndexFile *index;
|
||||
cUnbufferedFile *recordFile;
|
||||
diff -Naur vdr-2.1.6/remux.c vdr-2.1.6-naludump-0.1/remux.c
|
||||
--- vdr-2.1.6/remux.c 2014-03-08 16:05:35.000000000 +0100
|
||||
+++ vdr-2.1.6-naludump-0.1/remux.c 2014-03-30 17:47:25.000000000 +0200
|
||||
@@ -343,6 +343,42 @@
|
||||
dsyslog("WARNING: required %d video TS packets to determine frame type", numPacketsPid);
|
||||
}
|
||||
|
||||
+void TsExtendAdaptionField(unsigned char *Packet, int ToLength)
|
||||
+{
|
||||
+ // Hint: ExtenAdaptionField(p, TsPayloadOffset(p) - 4) is a null operation
|
||||
+
|
||||
+ int Offset = TsPayloadOffset(Packet); // First byte after existing adaption field
|
||||
+
|
||||
+ if (ToLength <= 0)
|
||||
+ {
|
||||
+ // Remove adaption field
|
||||
+ Packet[3] = Packet[3] & ~TS_ADAPT_FIELD_EXISTS;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // Set adaption field present
|
||||
+ Packet[3] = Packet[3] | TS_ADAPT_FIELD_EXISTS;
|
||||
+
|
||||
+ // Set new length of adaption field:
|
||||
+ Packet[4] = ToLength <= TS_SIZE-4 ? ToLength-1 : TS_SIZE-4-1;
|
||||
+
|
||||
+ if (Packet[4] == TS_SIZE-4-1)
|
||||
+ {
|
||||
+ // No more payload, remove payload flag
|
||||
+ Packet[3] = Packet[3] & ~TS_PAYLOAD_EXISTS;
|
||||
+ }
|
||||
+
|
||||
+ int NewPayload = TsPayloadOffset(Packet); // First byte after new adaption field
|
||||
+
|
||||
+ // Fill new adaption field
|
||||
+ if (Offset == 4 && Offset < NewPayload)
|
||||
+ Offset++; // skip adaptation_field_length
|
||||
+ if (Offset == 5 && Offset < NewPayload)
|
||||
+ Packet[Offset++] = 0; // various flags set to 0
|
||||
+ while (Offset < NewPayload)
|
||||
+ Packet[Offset++] = 0xff; // stuffing byte
|
||||
+}
|
||||
+
|
||||
// --- cPatPmtGenerator ------------------------------------------------------
|
||||
|
||||
cPatPmtGenerator::cPatPmtGenerator(const cChannel *Channel)
|
||||
@@ -1547,3 +1583,344 @@
|
||||
}
|
||||
return Processed;
|
||||
}
|
||||
+
|
||||
+// --- cNaluDumper ---------------------------------------------------------
|
||||
+
|
||||
+cNaluDumper::cNaluDumper()
|
||||
+{
|
||||
+ LastContinuityOutput = -1;
|
||||
+ reset();
|
||||
+}
|
||||
+
|
||||
+void cNaluDumper::reset()
|
||||
+{
|
||||
+ LastContinuityInput = -1;
|
||||
+ ContinuityOffset = 0;
|
||||
+ PesId = -1;
|
||||
+ PesOffset = 0;
|
||||
+ NaluFillState = NALU_NONE;
|
||||
+ NaluOffset = 0;
|
||||
+ History = 0xffffffff;
|
||||
+ DropAllPayload = false;
|
||||
+}
|
||||
+
|
||||
+void cNaluDumper::ProcessPayload(unsigned char *Payload, int size, bool PayloadStart, sPayloadInfo &Info)
|
||||
+{
|
||||
+ Info.DropPayloadStartBytes = 0;
|
||||
+ Info.DropPayloadEndBytes = 0;
|
||||
+ int LastKeepByte = -1;
|
||||
+
|
||||
+ if (PayloadStart)
|
||||
+ {
|
||||
+ History = 0xffffffff;
|
||||
+ PesId = -1;
|
||||
+ NaluFillState = NALU_NONE;
|
||||
+ }
|
||||
+
|
||||
+ for (int i=0; i<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
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,102 +0,0 @@
|
|||
--- a/diseqc.c 2015/01/26 12:02:14 4.0
|
||||
+++ b/diseqc.c 2017/01/09 15:10:40
|
||||
@@ -253,10 +253,10 @@
|
||||
return result;
|
||||
}
|
||||
|
||||
-uint cDiseqc::SetScrFrequency(uint SatFrequency, const cScr *Scr, uint8_t *Codes) const
|
||||
+int cDiseqc::SetScrFrequency(int SatFrequency, const cScr *Scr, uint8_t *Codes) const
|
||||
{
|
||||
if ((Codes[0] & 0xF0) == 0x70 ) { // EN50607 aka JESS
|
||||
- uint t = SatFrequency == 0 ? 0 : (SatFrequency - 100);
|
||||
+ int t = SatFrequency == 0 ? 0 : (SatFrequency - 100);
|
||||
if (t < 2048 && Scr->Channel() >= 0 && Scr->Channel() < 32) {
|
||||
Codes[1] = t >> 8 | Scr->Channel() << 3;
|
||||
Codes[2] = t;
|
||||
@@ -266,7 +266,7 @@
|
||||
}
|
||||
}
|
||||
else { // EN50494 aka Unicable
|
||||
- uint t = SatFrequency == 0 ? 0 : (SatFrequency + Scr->UserBand() + 2) / 4 - 350; // '+ 2' together with '/ 4' results in rounding!
|
||||
+ int t = SatFrequency == 0 ? 0 : (SatFrequency + Scr->UserBand() + 2) / 4 - 350; // '+ 2' together with '/ 4' results in rounding!
|
||||
if (t < 1024 && Scr->Channel() >= 0 && Scr->Channel() < 8) {
|
||||
Codes[3] = t >> 8 | (t == 0 ? 0 : scrBank << 2) | Scr->Channel() << 5;
|
||||
Codes[4] = t;
|
||||
@@ -399,7 +399,7 @@
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, uint *Frequency) const
|
||||
+cDiseqc::eDiseqcActions cDiseqc::Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, int *Frequency) const
|
||||
{
|
||||
if (!*CurrentAction)
|
||||
*CurrentAction = commands;
|
||||
--- a/diseqc.h 2013/06/12 11:52:17 4.0
|
||||
+++ b/diseqc.h 2017/01/09 15:11:19
|
||||
@@ -86,7 +86,7 @@
|
||||
mutable int scrBank;
|
||||
char *commands;
|
||||
bool parsing;
|
||||
- uint SetScrFrequency(uint SatFrequency, const cScr *Scr, uint8_t *Codes) const;
|
||||
+ int SetScrFrequency(int SatFrequency, const cScr *Scr, uint8_t *Codes) const;
|
||||
int SetScrPin(const cScr *Scr, uint8_t *Codes) const;
|
||||
const char *Wait(const char *s) const;
|
||||
const char *GetPosition(const char *s) const;
|
||||
@@ -96,7 +96,7 @@
|
||||
cDiseqc(void);
|
||||
~cDiseqc();
|
||||
bool Parse(const char *s);
|
||||
- eDiseqcActions Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, uint *Frequency) const;
|
||||
+ eDiseqcActions Execute(const char **CurrentAction, uchar *Codes, uint8_t *MaxCodes, const cScr *Scr, int *Frequency) const;
|
||||
///< Parses the DiSEqC commands and returns the appropriate action code
|
||||
///< with every call. CurrentAction must be the address of a character pointer,
|
||||
///< which is initialized to NULL. This pointer is used internally while parsing
|
||||
--- a/dvbdevice.c 2016/11/07 13:55:58 4.3
|
||||
+++ b/dvbdevice.c 2017/01/09 15:11:39
|
||||
@@ -329,7 +329,7 @@
|
||||
void ClearEventQueue(void) const;
|
||||
bool GetFrontendStatus(fe_status_t &Status) const;
|
||||
cPositioner *GetPositioner(void);
|
||||
- void ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency);
|
||||
+ void ExecuteDiseqc(const cDiseqc *Diseqc, int *Frequency);
|
||||
void ResetToneAndVoltage(void);
|
||||
bool SetFrontend(void);
|
||||
virtual void Action(void);
|
||||
@@ -696,7 +696,7 @@
|
||||
return positioner;
|
||||
}
|
||||
|
||||
-void cDvbTuner::ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency)
|
||||
+void cDvbTuner::ExecuteDiseqc(const cDiseqc *Diseqc, int *Frequency)
|
||||
{
|
||||
if (!lnbPowerTurnedOn) {
|
||||
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); // must explicitly turn on LNB power
|
||||
@@ -806,7 +806,7 @@
|
||||
|
||||
SETCMD(DTV_DELIVERY_SYSTEM, frontendType);
|
||||
if (frontendType == SYS_DVBS || frontendType == SYS_DVBS2) {
|
||||
- unsigned int frequency = channel.Frequency();
|
||||
+ int frequency = channel.Frequency();
|
||||
if (Setup.DiSEqC) {
|
||||
if (const cDiseqc *diseqc = Diseqcs.Get(device->CardIndex() + 1, channel.Source(), frequency, dtp.Polarization(), &scr)) {
|
||||
frequency -= diseqc->Lof();
|
||||
@@ -829,7 +829,7 @@
|
||||
}
|
||||
else {
|
||||
int tone = SEC_TONE_OFF;
|
||||
- if (frequency < (unsigned int)Setup.LnbSLOF) {
|
||||
+ if (frequency < Setup.LnbSLOF) {
|
||||
frequency -= Setup.LnbFrequLo;
|
||||
tone = SEC_TONE_OFF;
|
||||
}
|
||||
--- a/remux.c.orig 2017-03-02 13:22:31.133182283 +0100
|
||||
+++ b/remux.c 2017-03-02 13:23:50.300598025 +0100
|
||||
@@ -1638,7 +1638,7 @@
|
||||
Div += parser->IFrameTemporalReferenceOffset();
|
||||
if (Div <= 0)
|
||||
Div = 1;
|
||||
- uint32_t Delta = ptsValues[0] / Div;
|
||||
+ int Delta = ptsValues[0] / Div;
|
||||
// determine frame info:
|
||||
if (isVideo) {
|
||||
if (abs(Delta - 3600) <= 1)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
# This patch fixes a bug in handling the tfRecording flag in the SVDRP commands MODT
|
||||
# and UPDT. The tfRecording flag must only be handled by the VDR that actually hosts
|
||||
# and processes the timer.
|
||||
#
|
||||
--- svdrp.c 2018/03/19 12:16:33 5.0
|
||||
+++ svdrp.c 2018/04/19 09:45:08
|
||||
@@ -2036,6 +2036,7 @@
|
||||
LOCK_TIMERS_WRITE;
|
||||
Timers->SetExplicitModify();
|
||||
if (cTimer *Timer = Timers->GetById(Id)) {
|
||||
+ bool IsRecording = Timer->HasFlags(tfRecording);
|
||||
cTimer t = *Timer;
|
||||
if (strcasecmp(tail, "ON") == 0)
|
||||
t.SetFlags(tfActive);
|
||||
@@ -2046,6 +2047,10 @@
|
||||
return;
|
||||
}
|
||||
*Timer = t;
|
||||
+ if (IsRecording)
|
||||
+ Timer->SetFlags(tfRecording);
|
||||
+ else
|
||||
+ Timer->ClrFlags(tfRecording);
|
||||
Timers->SetModified();
|
||||
isyslog("SVDRP %s < %s modified timer %s (%s)", Setup.SVDRPHostName, *clientName, *Timer->ToDescr(), Timer->HasFlags(tfActive) ? "active" : "inactive");
|
||||
Reply(250, "%d %s", Timer->Id(), *Timer->ToText(true));
|
||||
@@ -2478,12 +2483,18 @@
|
||||
if (Timer->Parse(Option)) {
|
||||
LOCK_TIMERS_WRITE;
|
||||
if (cTimer *t = Timers->GetTimer(Timer)) {
|
||||
+ bool IsRecording = t->HasFlags(tfRecording);
|
||||
t->Parse(Option);
|
||||
delete Timer;
|
||||
Timer = t;
|
||||
+ if (IsRecording)
|
||||
+ Timer->SetFlags(tfRecording);
|
||||
+ else
|
||||
+ Timer->ClrFlags(tfRecording);
|
||||
isyslog("SVDRP %s < %s updated timer %s", Setup.SVDRPHostName, *clientName, *Timer->ToDescr());
|
||||
}
|
||||
else {
|
||||
+ Timer->ClrFlags(tfRecording);
|
||||
Timers->Add(Timer);
|
||||
isyslog("SVDRP %s < %s added timer %s", Setup.SVDRPHostName, *clientName, *Timer->ToDescr());
|
||||
}
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
--- vdr-2.4.0/config.h.orig 2018-04-16 09:36:30.655036427 +0200
|
||||
+++ vdr-2.4.0/config.h 2018-04-16 09:37:43.068036894 +0200
|
||||
@@ -47,6 +47,10 @@
|
||||
#define TIMERMACRO_TITLE "TITLE"
|
||||
#define TIMERMACRO_EPISODE "EPISODE"
|
||||
|
||||
+// The MainMenuHook Patch's version number:
|
||||
+#define MAINMENUHOOKSVERSION "1.0.1"
|
||||
+#define MAINMENUHOOKSVERSNUM 10001 // Version * 10000 + Major * 100 + Minor
|
||||
+
|
||||
#define MINOSDWIDTH 480
|
||||
#define MAXOSDWIDTH 1920
|
||||
#define MINOSDHEIGHT 324
|
||||
--- vdr-2.4.0/menu.c.orig 2018-04-16 09:39:22.013037531 +0200
|
||||
+++ vdr-2.4.0/menu.c 2018-04-16 10:24:50.584055109 +0200
|
||||
@@ -4475,16 +4475,31 @@
|
||||
Set();
|
||||
|
||||
// Initial submenus:
|
||||
-
|
||||
+ cOsdObject *menu = NULL;
|
||||
switch (State) {
|
||||
- case osSchedule: AddSubMenu(new cMenuSchedule); break;
|
||||
- case osChannels: AddSubMenu(new cMenuChannels); break;
|
||||
- case osTimers: AddSubMenu(new cMenuTimers); break;
|
||||
- case osRecordings: AddSubMenu(new cMenuRecordings(NULL, 0, OpenSubMenus)); break;
|
||||
- case osSetup: AddSubMenu(new cMenuSetup); break;
|
||||
- case osCommands: AddSubMenu(new cMenuCommands(tr("Commands"), &Commands)); break;
|
||||
+ case osSchedule:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu))
|
||||
+ menu = new cMenuSchedule;
|
||||
+ break;
|
||||
+ case osChannels:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu))
|
||||
+ menu = new cMenuChannels;
|
||||
+ break;
|
||||
+ case osTimers:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu))
|
||||
+ menu = new cMenuTimers;
|
||||
+ break;
|
||||
+ case osRecordings:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu))
|
||||
+ menu = new cMenuRecordings(NULL, 0, OpenSubMenus);
|
||||
+ break;
|
||||
+ case osSetup: menu = new cMenuSetup; break;
|
||||
+ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break;
|
||||
default: break;
|
||||
}
|
||||
+ if (menu)
|
||||
+ if (menu->IsMenu())
|
||||
+ AddSubMenu((cOsdMenu *) menu);
|
||||
}
|
||||
|
||||
cOsdObject *cMenuMain::PluginOsdObject(void)
|
||||
@@ -4592,13 +4607,34 @@
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
HadSubMenu |= HasSubMenu();
|
||||
|
||||
+ cOsdObject *menu = NULL;
|
||||
switch (state) {
|
||||
- case osSchedule: return AddSubMenu(new cMenuSchedule);
|
||||
- case osChannels: return AddSubMenu(new cMenuChannels);
|
||||
- case osTimers: return AddSubMenu(new cMenuTimers);
|
||||
- case osRecordings: return AddSubMenu(new cMenuRecordings);
|
||||
- case osSetup: return AddSubMenu(new cMenuSetup);
|
||||
- case osCommands: return AddSubMenu(new cMenuCommands(tr("Commands"), &Commands));
|
||||
+ case osSchedule:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osSchedule", &menu))
|
||||
+ menu = new cMenuSchedule;
|
||||
+ else
|
||||
+ state = osContinue;
|
||||
+ break;
|
||||
+ case osChannels:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osChannels", &menu))
|
||||
+ menu = new cMenuChannels;
|
||||
+ else
|
||||
+ state = osContinue;
|
||||
+ break;
|
||||
+ case osTimers:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osTimers", &menu))
|
||||
+ menu = new cMenuTimers;
|
||||
+ else
|
||||
+ state = osContinue;
|
||||
+ break;
|
||||
+ case osRecordings:
|
||||
+ if (!cPluginManager::CallFirstService("MainMenuHooksPatch-v1.0::osRecordings", &menu))
|
||||
+ menu = new cMenuRecordings;
|
||||
+ else
|
||||
+ state = osContinue;
|
||||
+ break;
|
||||
+ case osSetup: menu = new cMenuSetup; break;
|
||||
+ case osCommands: menu = new cMenuCommands(tr("Commands"), &Commands); break;
|
||||
case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) {
|
||||
if (cOsdItem *item = Get(Current())) {
|
||||
cRecordControls::Stop(item->Text() + strlen(tr(STOP_RECORDING)));
|
||||
@@ -4649,6 +4685,12 @@
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
+ if (menu) {
|
||||
+ if (menu->IsMenu())
|
||||
+ return AddSubMenu((cOsdMenu *) menu);
|
||||
+ pluginOsdObject = menu;
|
||||
+ return osPlugin;
|
||||
+ }
|
||||
if (!HasSubMenu() && Update(HadSubMenu))
|
||||
Display();
|
||||
if (Key != kNone) {
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
From dcfa8ba29f4c95edbdceb0f1bbae0e62fa40c4e2 Mon Sep 17 00:00:00 2001
|
||||
From: Manuel Reimer <manuel.reimer@gmx.de>
|
||||
Date: Sat, 14 Dec 2019 12:01:13 +0100
|
||||
Subject: [PATCH] Replace obsolete stime() function with clock_settime()
|
||||
|
||||
---
|
||||
eit.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/eit.c b/eit.c
|
||||
index 50d8229..82294dc 100644
|
||||
--- a/eit.c
|
||||
+++ b/eit.c
|
||||
@@ -391,7 +391,9 @@ cTDT::cTDT(const u_char *Data)
|
||||
if (abs(diff) > MAX_TIME_DIFF) {
|
||||
mutex.Lock();
|
||||
if (abs(diff) > MAX_ADJ_DIFF) {
|
||||
- if (stime(&dvbtim) == 0)
|
||||
+ timespec ts = {};
|
||||
+ ts.tv_sec = dvbtim;
|
||||
+ if (clock_settime(CLOCK_REALTIME, &ts) == 0)
|
||||
isyslog("system time changed from %s (%ld) to %s (%ld)", *TimeToString(loctim), loctim, *TimeToString(dvbtim), dvbtim);
|
||||
else
|
||||
esyslog("ERROR while setting system time: %m");
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
diff -Nurp vdr-2.4.1.orig/channels.c vdr-2.4.1.NitTid/channels.c
|
||||
--- vdr-2.4.1.orig/channels.c 2017-06-10 17:08:56.000000000 +0200
|
||||
+++ vdr-2.4.1.NitTid/channels.c 2019-09-24 20:48:49.243342312 +0200
|
||||
@@ -1096,11 +1096,13 @@ cChannel *cChannels::NewChannel(const cC
|
||||
#define CHANNELMARKOBSOLETE "OBSOLETE"
|
||||
#define CHANNELTIMEOBSOLETE 3600 // seconds to wait before declaring a channel obsolete (in case it has actually been seen before)
|
||||
|
||||
-bool cChannels::MarkObsoleteChannels(int Source, int Nid, int Tid)
|
||||
+bool cChannels::MarkObsoleteChannels(int Source, int Nid, int Tid, int Transponder)
|
||||
{
|
||||
bool ChannelsModified = false;
|
||||
for (cChannel *Channel = First(); Channel; Channel = Next(Channel)) {
|
||||
if (time(NULL) - Channel->Seen() > CHANNELTIMEOBSOLETE && Channel->Source() == Source && Channel->Nid() == Nid && Channel->Tid() == Tid && Channel->Rid() == 0) {
|
||||
+ if (Transponder && !ISTRANSPONDER(Channel->Transponder(), Transponder)) // mark channels only on specified transponder
|
||||
+ continue;
|
||||
int OldShowChannelNamesWithSource = Setup.ShowChannelNamesWithSource;
|
||||
Setup.ShowChannelNamesWithSource = 0;
|
||||
if (!endswith(Channel->Name(), CHANNELMARKOBSOLETE))
|
||||
diff -Nurp vdr-2.4.1.orig/channels.h vdr-2.4.1.NitTid/channels.h
|
||||
--- vdr-2.4.1.orig/channels.h 2017-06-10 17:06:40.000000000 +0200
|
||||
+++ vdr-2.4.1.NitTid/channels.h 2019-09-23 22:46:20.231197911 +0200
|
||||
@@ -251,7 +251,7 @@ public:
|
||||
///< and will be set to the current value of the list's internal state variable upon
|
||||
///< return from this function.
|
||||
cChannel *NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid = 0);
|
||||
- bool MarkObsoleteChannels(int Source, int Nid, int Tid);
|
||||
+ bool MarkObsoleteChannels(int Source, int Nid, int Tid, int Transponder = 0);
|
||||
};
|
||||
|
||||
// Provide lock controlled access to the list:
|
||||
diff -Nurp vdr-2.4.1.orig/eitscan.c vdr-2.4.1.NitTid/eitscan.c
|
||||
--- vdr-2.4.1.orig/eitscan.c 2019-03-12 12:54:27.000000000 +0100
|
||||
+++ vdr-2.4.1.NitTid/eitscan.c 2019-09-23 23:31:26.778124945 +0200
|
||||
@@ -60,8 +60,11 @@ void cScanList::AddTransponder(const cCh
|
||||
{
|
||||
if (Channel->Source() && Channel->Transponder()) {
|
||||
for (cScanData *sd = First(); sd; sd = Next(sd)) {
|
||||
- if (sd->Source() == Channel->Source() && ISTRANSPONDER(sd->Transponder(), Channel->Transponder()))
|
||||
- return;
|
||||
+ if (sd->Source() == Channel->Source() && ISTRANSPONDER(sd->Transponder(), Channel->Transponder())) {
|
||||
+ const cChannel *ch = sd->GetChannel();
|
||||
+ if (ch->Nid() == Channel->Nid() && ch->Tid() == Channel->Tid()) // add a channel for each unique transponder/Nid/Tid triple
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
Add(new cScanData(Channel));
|
||||
}
|
||||
@@ -78,8 +81,10 @@ void cTransponderList::AddTransponder(cC
|
||||
{
|
||||
for (cChannel *ch = First(); ch; ch = Next(ch)) {
|
||||
if (ch->Source() == Channel->Source() && ch->Transponder() == Channel->Transponder()) {
|
||||
- delete Channel;
|
||||
- return;
|
||||
+ if (ch->Nid() == Channel->Nid() && ch->Tid() == Channel->Tid()) { // add a channel for each unique transponder/Nid/Tid triple
|
||||
+ delete Channel;
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
Add(Channel);
|
||||
diff -Nurp vdr-2.4.1.orig/nit.c vdr-2.4.1.NitTid/nit.c
|
||||
--- vdr-2.4.1.orig/nit.c 2019-05-31 23:47:02.000000000 +0200
|
||||
+++ vdr-2.4.1.NitTid/nit.c 2019-09-25 00:09:04.140501158 +0200
|
||||
@@ -107,6 +107,7 @@ void cNitFilter::Process(u_short Pid, u_
|
||||
}
|
||||
|
||||
for (SI::Loop::Iterator it2; (d = ts.transportStreamDescriptors.getNext(it2)); ) {
|
||||
+ int tsTransponder = 0;
|
||||
switch (d->getDescriptorTag()) {
|
||||
case SI::SatelliteDeliverySystemDescriptorTag: {
|
||||
SI::SatelliteDeliverySystemDescriptor *sd = (SI::SatelliteDeliverySystemDescriptor *)d;
|
||||
@@ -125,6 +126,7 @@ void cNitFilter::Process(u_short Pid, u_
|
||||
dtp.SetRollOff(System ? RollOffs[sd->getRollOff()] : ROLLOFF_AUTO);
|
||||
int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
|
||||
dbgnit(" %s %d %c %d %d DVB-S%d\n", *cSource::ToString(Source), Frequency, dtp.Polarization(), SymbolRate, cChannel::Transponder(Frequency, dtp.Polarization()), System ? 2 : 1);
|
||||
+ tsTransponder = cChannel::Transponder(Frequency, dtp.Polarization());
|
||||
if (Setup.UpdateChannels >= 5) {
|
||||
bool found = false;
|
||||
bool forceTransponderUpdate = false;
|
||||
@@ -192,6 +194,7 @@ void cNitFilter::Process(u_short Pid, u_
|
||||
dtp.SetModulation(Modulations[min(sd->getModulation(), 6)]);
|
||||
int SymbolRate = BCD2INT(sd->getSymbolRate()) / 10;
|
||||
dbgnit(" %s %d %d %d %d\n", *cSource::ToString(Source), Frequency, dtp.CoderateH(), dtp.Modulation(), SymbolRate);
|
||||
+ tsTransponder = Frequency / 1000;
|
||||
if (Setup.UpdateChannels >= 5) {
|
||||
bool found = false;
|
||||
bool forceTransponderUpdate = false;
|
||||
@@ -248,6 +251,7 @@ void cNitFilter::Process(u_short Pid, u_
|
||||
static int TransmissionModes[] = { TRANSMISSION_MODE_2K, TRANSMISSION_MODE_8K, TRANSMISSION_MODE_4K, TRANSMISSION_MODE_AUTO };
|
||||
dtp.SetTransmission(TransmissionModes[sd->getTransmissionMode()]);
|
||||
dbgnit(" %s %d %d %d %d %d %d %d %d\n", *cSource::ToString(Source), Frequency, dtp.Bandwidth(), dtp.Modulation(), dtp.Hierarchy(), dtp.CoderateH(), dtp.CoderateL(), dtp.Guard(), dtp.Transmission());
|
||||
+ tsTransponder = Frequency / 1000000;
|
||||
if (Setup.UpdateChannels >= 5) {
|
||||
bool found = false;
|
||||
bool forceTransponderUpdate = false;
|
||||
@@ -298,6 +302,7 @@ void cNitFilter::Process(u_short Pid, u_
|
||||
SI::ExtensionDescriptor *sd = (SI::ExtensionDescriptor *)d;
|
||||
switch (sd->getExtensionDescriptorTag()) {
|
||||
case SI::T2DeliverySystemDescriptorTag: {
|
||||
+ tsTransponder = Transponder();
|
||||
if (Setup.UpdateChannels >= 5) {
|
||||
for (cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) {
|
||||
int Source = cSource::FromData(cSource::stTerr);
|
||||
@@ -368,6 +373,11 @@ void cNitFilter::Process(u_short Pid, u_
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
+ if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3) {
|
||||
+ // mark all channels with obsolete Nid/Tid on tuned transponder
|
||||
+ if (tsTransponder && ISTRANSPONDER(tsTransponder, Transponder()) && (Channel()->Nid() != ts.getOriginalNetworkId() || Channel()->Tid() != ts.getTransportStreamId()))
|
||||
+ ChannelsModified |= Channels->MarkObsoleteChannels(Source(), Channel()->Nid(), Channel()->Tid(), Transponder());
|
||||
+ }
|
||||
delete d;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
Description: Log an error message when skincures can't initialize the screen
|
||||
Author: Tobias Grimm <etobi@debian.org>
|
||||
|
||||
--- a/PLUGINS/src/skincurses/skincurses.c.orig 2019-06-17 18:31:59.351079418 +0200
|
||||
+++ b/PLUGINS/src/skincurses/skincurses.c 2019-06-17 18:35:21.586034302 +0200
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <vdr/plugin.h>
|
||||
#include <vdr/skins.h>
|
||||
#include <vdr/videodir.h>
|
||||
+#include <vdr/tools.h>
|
||||
|
||||
static const char *VERSION = "2.4.1";
|
||||
static const char *DESCRIPTION = trNOOP("A text only skin");
|
||||
@@ -841,6 +842,7 @@
|
||||
ScOsdHeight = maxy - begy + 1;
|
||||
return true;
|
||||
}
|
||||
+ esyslog("skincurses: unable to initialize curses screen");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
diff --git a/recording.h b/recording.h
|
||||
index 6f26f2f6..718df343 100644
|
||||
--- a/recording.h
|
||||
+++ b/recording.h
|
||||
@@ -41,6 +41,11 @@ enum eRecordingUsage {
|
||||
ruCanceled = 0x8000, // the operation has been canceled, waiting for cleanup
|
||||
};
|
||||
|
||||
+// workaround patch for enabling extra features in extrecmenung until vdr 2.5.2 is released
|
||||
+#ifndef EPGRENAME
|
||||
+#define EPGRENAME
|
||||
+#endif
|
||||
+
|
||||
void RemoveDeletedRecordings(void);
|
||||
void AssertFreeDiskSpace(int Priority = 0, bool Force = false);
|
||||
///< The special Priority value -1 means that we shall get rid of any
|
||||
@@ -74,8 +79,6 @@ private:
|
||||
char *fileName;
|
||||
cRecordingInfo(const cChannel *Channel = NULL, const cEvent *Event = NULL);
|
||||
bool Read(FILE *f);
|
||||
- void SetData(const char *Title, const char *ShortText, const char *Description);
|
||||
- void SetAux(const char *Aux);
|
||||
public:
|
||||
cRecordingInfo(const char *FileName);
|
||||
~cRecordingInfo();
|
||||
@@ -93,6 +96,8 @@ public:
|
||||
bool Write(FILE *f, const char *Prefix = "") const;
|
||||
bool Read(void);
|
||||
bool Write(void) const;
|
||||
+ void SetData(const char *Title, const char *ShortText, const char *Description);
|
||||
+ void SetAux(const char *Aux);
|
||||
};
|
||||
|
||||
class cRecording : public cListObject {
|
||||
@@ -150,7 +155,7 @@ public:
|
||||
///< Returns the full path name to the recording directory, including the
|
||||
///< video directory and the actual '*.rec'. For disk file access use.
|
||||
const char *Title(char Delimiter = ' ', bool NewIndicator = false, int Level = -1) const;
|
||||
- const cRecordingInfo *Info(void) const { return info; }
|
||||
+ cRecordingInfo *Info(void) const { return info; }
|
||||
const char *PrefixFileName(char Prefix);
|
||||
int HierarchyLevels(void) const;
|
||||
void ResetResume(void) const;
|
||||
diff --git a/recording.c b/recording.c
|
||||
index 17467e36..a7f08a26 100644
|
||||
--- a/recording.c
|
||||
+++ b/recording.c
|
||||
@@ -430,11 +430,11 @@ cRecordingInfo::~cRecordingInfo()
|
||||
|
||||
void cRecordingInfo::SetData(const char *Title, const char *ShortText, const char *Description)
|
||||
{
|
||||
- if (!isempty(Title))
|
||||
+ if (Title)
|
||||
((cEvent *)event)->SetTitle(Title);
|
||||
- if (!isempty(ShortText))
|
||||
+ if (ShortText)
|
||||
((cEvent *)event)->SetShortText(ShortText);
|
||||
- if (!isempty(Description))
|
||||
+ if (Description)
|
||||
((cEvent *)event)->SetDescription(Description);
|
||||
}
|
||||
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
diff -Nurp vdr-2.4.6.orig/channels.c vdr-2.4.6/channels.c
|
||||
--- vdr-2.4.6.orig/channels.c 2020-04-11 11:22:05.000000000 +0200
|
||||
+++ vdr-2.4.6/channels.c 2021-01-01 12:35:10.946734352 +0100
|
||||
@@ -1115,11 +1116,20 @@ cChannel *cChannels::NewChannel(const cC
|
||||
#define CHANNELMARKOBSOLETE "OBSOLETE"
|
||||
#define CHANNELTIMEOBSOLETE 3600 // seconds to wait before declaring a channel obsolete (in case it has actually been seen before)
|
||||
|
||||
-bool cChannels::MarkObsoleteChannels(int Source, int Nid, int Tid)
|
||||
+bool cChannels::MarkObsoleteChannels(int Source, int Transponder, int StreamId, int Nid, int Tid)
|
||||
{
|
||||
bool ChannelsModified = false;
|
||||
for (cChannel *Channel = First(); Channel; Channel = Next(Channel)) {
|
||||
- if (time(NULL) - Channel->Seen() > CHANNELTIMEOBSOLETE && Channel->Source() == Source && Channel->Nid() == Nid && Channel->Tid() == Tid && Channel->Rid() == 0) {
|
||||
+ if (Channel->Source() != Source)
|
||||
+ continue;
|
||||
+ bool obsolete = false;
|
||||
+ if (Channel->Nid() == Nid && Channel->Tid() == Tid)
|
||||
+ obsolete = time(NULL) - Channel->Seen() > CHANNELTIMEOBSOLETE && Channel->Rid() == 0; // obsolete Sid
|
||||
+ else if (ISTRANSPONDER(Channel->Transponder(), Transponder)) {
|
||||
+ cDvbTransponderParameters dtp(Channel->Parameters());
|
||||
+ obsolete = dtp.StreamId() == StreamId; // obsolete Nid/Tid
|
||||
+ }
|
||||
+ if (obsolete) {
|
||||
int OldShowChannelNamesWithSource = Setup.ShowChannelNamesWithSource;
|
||||
Setup.ShowChannelNamesWithSource = 0;
|
||||
if (!endswith(Channel->Name(), CHANNELMARKOBSOLETE))
|
||||
diff -Nurp vdr-2.4.6.orig/channels.h vdr-2.4.6/channels.h
|
||||
--- vdr-2.4.6.orig/channels.h 2020-06-10 16:00:36.000000000 +0200
|
||||
+++ vdr-2.4.6/channels.h 2020-12-31 18:35:07.050191444 +0100
|
||||
@@ -252,7 +252,7 @@ public:
|
||||
///< and will be set to the current value of the list's internal state variable upon
|
||||
///< return from this function.
|
||||
cChannel *NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid = 0);
|
||||
- bool MarkObsoleteChannels(int Source, int Nid, int Tid);
|
||||
+ bool MarkObsoleteChannels(int Source, int Transponder, int Streamid, int Nid, int Tid);
|
||||
};
|
||||
|
||||
// Provide lock controlled access to the list:
|
||||
diff -Nurp vdr-2.4.6.orig/sdt.c vdr-2.4.6/sdt.c
|
||||
--- vdr-2.4.6.orig/sdt.c 2020-06-16 16:50:07.000000000 +0200
|
||||
+++ vdr-2.4.6/sdt.c 2020-12-31 18:40:31.853536210 +0100
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "config.h"
|
||||
#include "libsi/section.h"
|
||||
#include "libsi/descriptor.h"
|
||||
+#include "dvbdevice.h"
|
||||
|
||||
// Set to 'true' for debug output:
|
||||
static bool DebugSdt = false;
|
||||
@@ -205,9 +206,10 @@ void cSdtFilter::Process(u_short Pid, u_
|
||||
}
|
||||
if (sdt.getSectionNumber() == sdt.getLastSectionNumber()) {
|
||||
if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3) {
|
||||
- ChannelsModified |= Channels->MarkObsoleteChannels(source, sdt.getOriginalNetworkId(), sdt.getTransportStreamId());
|
||||
+ cDvbTransponderParameters dtp(Channel()->Parameters());
|
||||
+ ChannelsModified |= Channels->MarkObsoleteChannels(source, Transponder(), dtp.StreamId(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId());
|
||||
if (source != Source())
|
||||
- ChannelsModified |= Channels->MarkObsoleteChannels(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId());
|
||||
+ ChannelsModified |= Channels->MarkObsoleteChannels(Source(), Transponder(), dtp.StreamId(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId());
|
||||
}
|
||||
}
|
||||
StateKey.Remove(ChannelsModified);
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
Fix compile with gcc-11, officially from kls
|
||||
|
||||
Signed-off-by: Martin Dummer <martin.dummer@gmx.net>
|
||||
|
||||
--- a/tools.h 2021/01/19 20:38:28 5.3
|
||||
+++ b/tools.h 2021/05/05 15:16:45
|
||||
@@ -53,17 +53,15 @@
|
||||
|
||||
// In case some plugin needs to use the STL and gets an error message regarding one
|
||||
// of these functions, you can #define DISABLE_TEMPLATES_COLLIDING_WITH_STL before
|
||||
-// including tools.h.
|
||||
-#if !defined(__STL_CONFIG_H) // for old versions of the STL
|
||||
-#if !defined(DISABLE_TEMPLATES_COLLIDING_WITH_STL) && !defined(_STL_ALGOBASE_H)
|
||||
+// including any VDR header files.
|
||||
+#if !defined(DISABLE_TEMPLATES_COLLIDING_WITH_STL)
|
||||
template<class T> inline T min(T a, T b) { return a <= b ? a : b; }
|
||||
template<class T> inline T max(T a, T b) { return a >= b ? a : b; }
|
||||
#endif
|
||||
template<class T> inline int sgn(T a) { return a < 0 ? -1 : a > 0 ? 1 : 0; }
|
||||
-#if !defined(DISABLE_TEMPLATES_COLLIDING_WITH_STL) && !defined(_MOVE_H)
|
||||
+#if !defined(DISABLE_TEMPLATES_COLLIDING_WITH_STL)
|
||||
template<class T> inline void swap(T &a, T &b) { T t = a; a = b; b = t; }
|
||||
#endif
|
||||
-#endif
|
||||
|
||||
template<class T> inline T constrain(T v, T l, T h) { return v < l ? l : v > h ? h : v; }
|
||||
Binary file not shown.
|
|
@ -1,11 +0,0 @@
|
|||
--- a/dvbplayer.c 2019/05/27 13:54:19 5.0
|
||||
+++ b/dvbplayer.c 2022/01/13 10:18:27
|
||||
@@ -914,7 +914,7 @@
|
||||
ptsIndex.Put(isPesRecording ? PesGetPts(b) : TsGetPts(b, r), Index, true);
|
||||
}
|
||||
playMode = pmStill;
|
||||
- readIndex = Index;
|
||||
+ readIndex = Index - 1; // makes sure a later play starts with this I-frame
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
--- a/recording.c 2022/11/28 14:39:23 5.19
|
||||
+++ b/recording.c 2022/12/01 12:39:42
|
||||
@@ -2579,7 +2579,7 @@
|
||||
cCondWait::SleepMs(INDEXFILETESTINTERVAL);
|
||||
}
|
||||
int delta = 0;
|
||||
- if (!Record && (access(fileName, R_OK) != 0 || FileSize(fileName) == 0)) {
|
||||
+ if (!Record && (access(fileName, R_OK) != 0 || FileSize(fileName) == 0 && time(NULL) - LastModifiedTime(fileName) > MAXWAITFORINDEXFILE)) {
|
||||
// Index file doesn't exist, so try to regenerate it:
|
||||
if (!isPesRecording) { // sorry, can only do this for TS recordings
|
||||
resumeFile.Delete(); // just in case
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
diff --git a/remux.c b/remux.c
|
||||
index 391fd6ff..54fc50fd 100644
|
||||
--- a/remux.c
|
||||
+++ b/remux.c
|
||||
@@ -1333,7 +1333,7 @@ int cMpeg2Parser::Parse(const uchar *Data, int Length, int Pid)
|
||||
seenScanType = true;
|
||||
if (debug) {
|
||||
cString s = cString::sprintf("MPEG2: %d x %d%c %.2f fps", frameWidth, frameHeight, progressive ? 'p' : 'i', framesPerSecond);
|
||||
- dsyslog(s);
|
||||
+ dsyslog("%s",*s);
|
||||
dbgframes("\n%s", *s);
|
||||
}
|
||||
}
|
||||
@@ -1607,7 +1607,7 @@ void cH264Parser::ParseSequenceParameterSet(void)
|
||||
}
|
||||
if (debug) {
|
||||
cString s = cString::sprintf("H.264: %d x %d%c %.2f fps %d Bit", frameWidth, frameHeight, progressive ? 'p':'i', framesPerSecond, bitDepth);
|
||||
- dsyslog(s);
|
||||
+ dsyslog("%s", *s);
|
||||
dbgframes("\n%s", *s);
|
||||
}
|
||||
}
|
||||
@@ -1908,7 +1908,7 @@ void cH265Parser::ParseSequenceParameterSet(void)
|
||||
}
|
||||
if (debug) {
|
||||
cString s = cString::sprintf("H.265: %d x %d%c %.2f fps %d Bit", frameWidth, frameHeight, progressive ? 'p':'i', framesPerSecond, bitDepth);
|
||||
- dsyslog(s);
|
||||
+ dsyslog("%s", *s);
|
||||
dbgframes("\n%s", *s);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
--- remux.c 2024/10/08 08:46:38 5.14
|
||||
+++ remux.c 2024/10/13 13:34:32
|
||||
@@ -2274,6 +2274,7 @@
|
||||
}
|
||||
else // audio
|
||||
framesPerSecond = double(PTSTICKS) / Delta; // PTS of audio frames is always increasing
|
||||
+ frameChecker->SetFrameDelta(Delta);
|
||||
dbgframes("\nDelta = %d FPS = %5.2f FPPU = %d NF = %d TRO = %d\n", Delta, framesPerSecond, framesPerPayloadUnit, numPtsValues + 1, parser->IFrameTemporalReferenceOffset());
|
||||
synced = true;
|
||||
parser->SetDebug(false);
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
diff -up vdr-1.6.0/menu.c~ vdr-1.6.0/menu.c
|
||||
--- vdr-1.6.0/menu.c~ 2008-03-16 13:15:28.000000000 +0200
|
||||
+++ vdr-1.6.0/menu.c 2011-02-15 00:39:42.267224859 +0200
|
||||
@@ -399,11 +399,20 @@ int cMenuChannelItem::Compare(const cLis
|
||||
void cMenuChannelItem::Set(void)
|
||||
{
|
||||
cString buffer;
|
||||
+ const cEvent *Event = NULL;
|
||||
if (!channel->GroupSep()) {
|
||||
+ cSchedulesLock SchedulesLock;
|
||||
+ const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
|
||||
+ const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
|
||||
+ if (Schedule)
|
||||
+ Event = Schedule->GetPresentEvent();
|
||||
+
|
||||
if (sortMode == csmProvider)
|
||||
- buffer = cString::sprintf("%d\t%s - %s", channel->Number(), channel->Provider(), channel->Name());
|
||||
+ buffer = cString::sprintf("%d\t%s - %s %c%s%c", channel->Number(), channel->Provider(), channel->Name(),
|
||||
+ Event ? '(' : ' ', Event ? Event->Title() : "", Event ? ')' : ' ');
|
||||
else
|
||||
- buffer = cString::sprintf("%d\t%s", channel->Number(), channel->Name());
|
||||
+ buffer = cString::sprintf("%d\t%s %c%s%c", channel->Number(), channel->Name(),
|
||||
+ Event ? '(' : ' ', Event ? Event->Title() : "", Event ? ')' : ' ');
|
||||
}
|
||||
else
|
||||
buffer = cString::sprintf("---\t%s ----------------------------------------------------------------", channel->Name());
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
diff --git a/recording.c b/recording.c
|
||||
index e493b57..e50ef7d 100644
|
||||
--- a/recording.c
|
||||
+++ b/recording.c
|
||||
@@ -3025,7 +3025,15 @@ cUnbufferedFile *cFileName::SetOffset(int Number, off_t Offset)
|
||||
}
|
||||
// found a non existing file suffix
|
||||
}
|
||||
- if (Open() >= 0) {
|
||||
+ /* This used to test Open() >= 0, but Open() returns a pointer
|
||||
+ and we shouldn't be doing ordered comparisons of pointers
|
||||
+ against constants. Furthermore, on some systems pointers
|
||||
+ are unsigned meaning this test always succeeded.
|
||||
+
|
||||
+ Finally, AFAICT Open() is always going to return NULL or a
|
||||
+ valid pointer and can never return a negative value based on my
|
||||
+ reading of these sources. */
|
||||
+ if (1) {
|
||||
if (!record && Offset >= 0 && file && file->Seek(Offset, SEEK_SET) != Offset) {
|
||||
LOG_ERROR_STR(fileName);
|
||||
return NULL;
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
--- a/osdbase.c.orig 2017-02-15 15:55:34.555128665 +0100
|
||||
+++ b/osdbase.c 2017-02-15 15:56:30.898068614 +0100
|
||||
@@ -510,7 +510,7 @@
|
||||
const char *s = item->Text();
|
||||
i = 0;
|
||||
item_nr = 0;
|
||||
- if (s && (s = skipspace(s)) != '\0' && '0' <= s[i] && s[i] <= '9') {
|
||||
+ if (s && (s = skipspace(s)) != NULL && '0' <= s[i] && s[i] <= '9') {
|
||||
do {
|
||||
item_nr = item_nr * 10 + (s[i] - '0');
|
||||
}
|
||||
|
|
@ -1,306 +0,0 @@
|
|||
#! /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)
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
diff --git a/menu.c b/menu.c
|
||||
index 14be0ed..9c6a0ff 100644
|
||||
--- a/menu.c
|
||||
+++ b/menu.c
|
||||
@@ -1377,8 +1377,8 @@ void cMenuTimers::ActualiseDiskStatus(void)
|
||||
|
||||
// compute free disk space
|
||||
int freeMB, freeMinutes, runshortMinutes;
|
||||
- VideoDiskSpace(&freeMB);
|
||||
- freeMinutes = int(double(freeMB) * 1.1 / MB_PER_MINUTE); // overestimate by 10 percent
|
||||
+ cVideoDirectory::VideoDiskSpace(&freeMB);
|
||||
+ freeMinutes = int(double(freeMB) * 1.1 / 25.75); // overestimate by 10 percent
|
||||
runshortMinutes = freeMinutes / 5; // 20 Percent
|
||||
|
||||
// fill entries list
|
||||
|
|
@ -1,110 +0,0 @@
|
|||
--- menu.c.orig 2009-04-11 14:47:08.000000000 +0200
|
||||
+++ menu.c 2009-04-17 13:53:05.000000000 +0200
|
||||
@@ -853,6 +853,7 @@ eOSState cMenuEditTimer::ProcessKey(eKey
|
||||
class cMenuTimerItem : public cOsdItem {
|
||||
private:
|
||||
cTimer *timer;
|
||||
+ void DoSet(void);
|
||||
public:
|
||||
cMenuTimerItem(cTimer *Timer);
|
||||
virtual int Compare(const cListObject &ListObject) const;
|
||||
@@ -863,7 +864,7 @@ public:
|
||||
cMenuTimerItem::cMenuTimerItem(cTimer *Timer)
|
||||
{
|
||||
timer = Timer;
|
||||
- Set();
|
||||
+ DoSet();
|
||||
}
|
||||
|
||||
int cMenuTimerItem::Compare(const cListObject &ListObject) const
|
||||
@@ -873,6 +874,18 @@ int cMenuTimerItem::Compare(const cListO
|
||||
|
||||
void cMenuTimerItem::Set(void)
|
||||
{
|
||||
+ // check for deleted timer
|
||||
+ for (cTimer *t = Timers.First(); ; t = Timers.Next(t)) {
|
||||
+ if (t == timer)
|
||||
+ break; // timer still there
|
||||
+ if (t == NULL)
|
||||
+ return; // no matching timer found
|
||||
+ }
|
||||
+ DoSet();
|
||||
+}
|
||||
+
|
||||
+void cMenuTimerItem::DoSet(void)
|
||||
+{
|
||||
cString day, name("");
|
||||
if (timer->WeekDays())
|
||||
day = timer->PrintDay(0, timer->WeekDays(), false);
|
||||
@@ -906,8 +919,7 @@ void cMenuTimerItem::Set(void)
|
||||
class cMenuTimers : public cOsdMenu {
|
||||
private:
|
||||
int helpKeys;
|
||||
- eOSState Edit(void);
|
||||
- eOSState New(void);
|
||||
+ eOSState Edit(bool New = false);
|
||||
eOSState Delete(void);
|
||||
eOSState OnOff(void);
|
||||
eOSState Info(void);
|
||||
@@ -980,19 +992,30 @@ eOSState cMenuTimers::OnOff(void)
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
-eOSState cMenuTimers::Edit(void)
|
||||
+eOSState cMenuTimers::Edit(bool New)
|
||||
{
|
||||
- if (HasSubMenu() || Count() == 0)
|
||||
+ if (HasSubMenu() || (Count() == 0 && !New))
|
||||
return osContinue;
|
||||
- isyslog("editing timer %s", *CurrentTimer()->ToDescr());
|
||||
- return AddSubMenu(new cMenuEditTimer(CurrentTimer()));
|
||||
-}
|
||||
+ if (!New)
|
||||
+ isyslog("editing timer %s", *CurrentTimer()->ToDescr());
|
||||
|
||||
-eOSState cMenuTimers::New(void)
|
||||
-{
|
||||
- if (HasSubMenu())
|
||||
- return osContinue;
|
||||
- return AddSubMenu(new cMenuEditTimer(new cTimer, true));
|
||||
+ // Data structure for service "Epgsearch-exttimeredit-v1.0"
|
||||
+ struct Epgsearch_exttimeredit_v1_0
|
||||
+ {
|
||||
+ // in
|
||||
+ cTimer* timer; // pointer to the timer to edit
|
||||
+ bool bNew; // flag that indicates, if this is a new timer or an existing one
|
||||
+ const cEvent* event; // pointer to the event corresponding to this timer (may be NULL)
|
||||
+ // out
|
||||
+ cOsdMenu* pTimerMenu; // pointer to the menu of results
|
||||
+ } exttimeredit;
|
||||
+ exttimeredit.timer = New ? (new cTimer) : CurrentTimer();
|
||||
+ exttimeredit.bNew = New;
|
||||
+ exttimeredit.event = exttimeredit.timer->Event();
|
||||
+ if (cPluginManager::CallFirstService("Epgsearch-exttimeredit-v1.0", &exttimeredit))
|
||||
+ return AddSubMenu(exttimeredit.pTimerMenu);
|
||||
+
|
||||
+ return AddSubMenu(new cMenuEditTimer(exttimeredit.timer, New));
|
||||
}
|
||||
|
||||
eOSState cMenuTimers::Delete(void)
|
||||
@@ -1038,7 +1061,7 @@ eOSState cMenuTimers::ProcessKey(eKeys K
|
||||
switch (Key) {
|
||||
case kOk: return Edit();
|
||||
case kRed: state = OnOff(); break; // must go through SetHelpKeys()!
|
||||
- case kGreen: return New();
|
||||
+ case kGreen: return Edit(true);
|
||||
case kYellow: state = Delete(); break;
|
||||
case kInfo:
|
||||
case kBlue: return Info();
|
||||
@@ -1051,6 +1074,11 @@ eOSState cMenuTimers::ProcessKey(eKeys K
|
||||
Add(new cMenuTimerItem(Timers.Get(TimerNumber)), true);
|
||||
Display();
|
||||
}
|
||||
+ if (!HasSubMenu() && Timers.Count()<Count()) {
|
||||
+ // timer was deleted
|
||||
+ cOsdMenu::Del(Current());
|
||||
+ Display();
|
||||
+ }
|
||||
if (Key != kNone)
|
||||
SetHelpKeys();
|
||||
return state;
|
||||
Loading…
Add table
Add a link
Reference in a new issue