mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Implemented "Pattern Timers"
This commit is contained in:
parent
d2e0087c4e
commit
2b3556b460
6
HISTORY
6
HISTORY
@ -9562,3 +9562,9 @@ Video Disk Recorder Revision History
|
||||
- Fixed a compiler warning (thanks to Winfried Köhler).
|
||||
- Fixed convertCharacterTable() in case iconv_open() fails (thanks to Helmut Binder).
|
||||
- Official release.
|
||||
|
||||
2020-12-26: Version 2.5.1
|
||||
|
||||
- Implemented "Pattern Timers" (see MANUAL, vdr.1 and vdr.5 for details).
|
||||
- Events in the past are no longer marked as having a timer in the Schedules
|
||||
menu.
|
||||
|
125
MANUAL
125
MANUAL
@ -480,6 +480,8 @@ Version 2.4
|
||||
"forever", and a value of 0 means that this recording can be
|
||||
deleted any time if a recording with a higher priority needs disk
|
||||
space.
|
||||
Pattern: The pattern to use for recordings matching events (only available
|
||||
for pattern timers). See section "Pattern timers" below.
|
||||
File: The name under which a recording created through this timer will
|
||||
be stored on disk (the actual name will also contain the date and
|
||||
time, so it is possible to have a "repeating timer" store all its
|
||||
@ -511,6 +513,129 @@ Version 2.4
|
||||
The "Red" key in the "Edit timer" menu opens a list of folders, which can be
|
||||
used to define the file name in which the recording will be stored.
|
||||
|
||||
The "Yellow" key in the "Edit timer" menu toggles the timer between "Pattern"
|
||||
and "Regular".
|
||||
|
||||
When editing the "File" field, the "Blue" key in can be used to insert useful
|
||||
macros.
|
||||
|
||||
* Pattern timers
|
||||
|
||||
There are cases where it would make sense to have a more flexible kind of
|
||||
recording timer. For instance, some channels that provide VPS don't always
|
||||
use the exact same VPS time for a series, which is extremely annoying.
|
||||
Or you might want to record all films that have a certain pattern in their
|
||||
title, no matter when they are broadcast. In such cases, "pattern timers"
|
||||
can help.
|
||||
|
||||
In the "Edit timer" menu press the Yellow button to turn a regular timer into
|
||||
a pattern timer. Pressing this button again switches back to regular.
|
||||
|
||||
The following rules apply to pattern timers:
|
||||
|
||||
- Pattern timers can only work for channels that provide EPG data.
|
||||
- When using pattern timers, there should always be at least one free device that
|
||||
can be used to regularly receive the EPG of the pattern timer's channel.
|
||||
- A pattern timer records every matching event on the given channel that overlaps
|
||||
with the given start/stop time. Overlapping events are recorded in full,
|
||||
even if they extend outside the given start/stop interval.
|
||||
- In order to actually record an event, a pattern timer "spawns" a separate timer
|
||||
that does the recording. At most two timers are spawned from a pattern timer at
|
||||
any given time, one for the next upcoming matching event, and one for
|
||||
the event immediately following that one, in case it also matches.
|
||||
- Spawned timers are marked with the flag tfSpawned.
|
||||
- Spawned timers take the Priority, Lifetime and VPS settings from the pattern timer.
|
||||
- The special pattern "*" matches every event. So a timer with
|
||||
a start/stop time of 00:00/23:59 will record every event of that day
|
||||
into separate recordings. Note that when using this pattern there should
|
||||
be no other timers for the same channel, because these might interfere.
|
||||
- Once a timer has been spawned, it is treated like any other regular
|
||||
timer. Any changes made to the corresponding pattern timer thereafter will have
|
||||
no effect on spawned timers. Note that after deleting a spawned timer,
|
||||
the corresponding pattern timer may respawn it.
|
||||
- Recording is done according to the event's begin/end times, either
|
||||
by adding the start/stop margins (for non-VPS timers) or by using the
|
||||
event's running status (for VPS timers).
|
||||
- The recording of a pattern timer is stored under the given file name, just like
|
||||
regular timers do. In addition to the "TITLE" and "EPISODE" macros the file
|
||||
name of a pattern timer can also use "{<}" and "{>}" to reference the part of the
|
||||
event's title before and after the pattern, respectively. For instance,
|
||||
if the event's title is "Abc def ghi" and the pattern is "def ", "{<}"
|
||||
would contain "Abc " and "{>}" would contain "ghi" (note the matching of the
|
||||
blanks). For completeness, "{=}" can be used to reference the matching
|
||||
pattern itself.
|
||||
- In the "Timers" menu pressing the Red button on a pattern timer only toggles the
|
||||
timer between "on" and "off", even if this is a repeating timer.
|
||||
- In the "Timers" menu pattern timers are sorted alphabetically to the end of the
|
||||
list of timers.
|
||||
- A regular timer that is currently recording can't be changed into a pattern timer.
|
||||
- In the "Edit timer" menu the file name and pattern are displayed as
|
||||
separate items. The Yellow button can be used to toggle between a regular
|
||||
timer and a pattern timer. When going from regular to pattern, the Pattern item will
|
||||
be initialized with the base part of the file name.
|
||||
- The characters '^' and '$' can be used at the very beginning and end of
|
||||
the pattern to anchor the pattern to the begin or end of the title.
|
||||
Using both of these will match only titles that consist of exactly the given pattern,
|
||||
with nothing before and nothing after it.
|
||||
- The Pattern field in the "Edit timer" menu allows blanks at the end of the string,
|
||||
which may help to separate the text after the matching pattern.
|
||||
- If the first character of the pattern is '@', an event that matches the
|
||||
rest of the pattern is only recorded if the resulting recording's file
|
||||
name (without any folders) is not contained in the donerecs.data file.
|
||||
This avoids duplicate recordings of the same programme. Timers spawned from
|
||||
such a pattern timer are marked with the flag tfAvoid.
|
||||
- When editing the "File" field of a timer, the Blue button can be pressed to
|
||||
insert one of the macros "TITLE", "EPISODE", "{<}", "{=}" or "{>}",
|
||||
respectively. Pressing the Blue button repeatedly loops through the available
|
||||
macros. The "{...}" macros are only available for pattern timers.
|
||||
- In the "Schedule" and "What's on...?" menus the events that will be recorded
|
||||
by a pattern timer are marked in the same way as regular timers.
|
||||
- The TIMERS column in the LCARS skin doesn't show the basic definitions of
|
||||
pattern timers, it only shows timers actually spawned from pattern timers.
|
||||
|
||||
If the pattern is prepended with '@', the name of the resulting recording (everything
|
||||
after the rightmost '~', or the entire file name, if there is no '~') will be stored
|
||||
in the file donerecs.data, so that multiple recordings of the same programme can be
|
||||
avoided. When using this feature, special care must be taken regarding the recording's
|
||||
file name. For instance, with a combination of
|
||||
|
||||
pattern file name
|
||||
@Columbo Movies~TITLE
|
||||
|
||||
if the event's title is just "Columbo", this pattern timer would only record once,
|
||||
and ignore any future events with that title, even if the episode would be different.
|
||||
So you may want to use the episode name, as in
|
||||
|
||||
pattern file name
|
||||
@Columbo Movies~TITLE - EPISODE
|
||||
|
||||
to make the file name unique. If you have several pattern timers for the same show on
|
||||
different channels, chances are that the broadcasters handle title and episode
|
||||
differently, as for example in
|
||||
|
||||
TITLE EPISODE pattern file name
|
||||
Columbo Blueprint for Murder @^Columbo$ TITLE - EPISODE
|
||||
Columbo - Blueprint for Murder @^Columbo TITLE
|
||||
Columbo: Blueprint for Murder @^Columbo:_ Columbo - {>}
|
||||
|
||||
(note the '_' in the pattern of the third example; this is just used to visualize
|
||||
the blank at the end of the pattern)
|
||||
|
||||
In order to have the same episode result in the same recording file name on all
|
||||
channels, the file name needs to be generated differently for each channel. First
|
||||
you need to decide on a proper combination of title and episode name, preferably
|
||||
one that is already used by one of your channels (let's say the second one).
|
||||
In the first case, title and episode name are correctly put in their respective
|
||||
places, and "TITLE - EPISODE" as file name will do. The second case is our common
|
||||
version, where everything is in the title, so TITLE is just fine. The third case
|
||||
poses a problem, because everything is in the title, but with a different separator.
|
||||
Here the special macro "{>}" can be used in the file name, which contains everything
|
||||
following the matching pattern. There are three macros that can be used here:
|
||||
|
||||
{<} everything before the matching pattern
|
||||
{>} everything after the matching pattern
|
||||
{=} the matching pattern itself (just for completeness)
|
||||
|
||||
* Managing folders
|
||||
|
||||
The "Select folder" menu, which can be accessed by pressing the "Red" key in
|
||||
|
17
config.h
17
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 4.21 2020/12/22 17:23:51 kls Exp $
|
||||
* $Id: config.h 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -22,13 +22,13 @@
|
||||
|
||||
// VDR's own version number:
|
||||
|
||||
#define VDRVERSION "2.4.6"
|
||||
#define VDRVERSNUM 20406 // Version * 10000 + Major * 100 + Minor
|
||||
#define VDRVERSION "2.5.1"
|
||||
#define VDRVERSNUM 20501 // Version * 10000 + Major * 100 + Minor
|
||||
|
||||
// The plugin API's version number:
|
||||
|
||||
#define APIVERSION "2.4.6"
|
||||
#define APIVERSNUM 20406 // Version * 10000 + Major * 100 + Minor
|
||||
#define APIVERSION "2.5.1"
|
||||
#define APIVERSNUM 20501 // Version * 10000 + Major * 100 + Minor
|
||||
|
||||
// When loading plugins, VDR searches them by their APIVERSION, which
|
||||
// may be smaller than VDRVERSION in case there have been no changes to
|
||||
@ -46,6 +46,13 @@
|
||||
|
||||
#define TIMERMACRO_TITLE "TITLE"
|
||||
#define TIMERMACRO_EPISODE "EPISODE"
|
||||
#define TIMERMACRO_BEFORE "{<}"
|
||||
#define TIMERMACRO_MATCH "{=}"
|
||||
#define TIMERMACRO_AFTER "{>}"
|
||||
|
||||
#define TIMERPATTERN_AVOID "@"
|
||||
#define TIMERPATTERN_BEGIN "^"
|
||||
#define TIMERPATTERN_END "$"
|
||||
|
||||
#define MINOSDWIDTH 480
|
||||
#define MAXOSDWIDTH 1920
|
||||
|
86
menu.c
86
menu.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.c 4.88 2020/12/12 22:01:01 kls Exp $
|
||||
* $Id: menu.c 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -993,6 +993,23 @@ eOSState cMenuFolder::ProcessKey(eKeys Key)
|
||||
|
||||
// --- cMenuEditTimer --------------------------------------------------------
|
||||
|
||||
static const char *TimerFileMacrosForPattern[] = {
|
||||
TIMERMACRO_TITLE,
|
||||
TIMERMACRO_EPISODE,
|
||||
TIMERMACRO_BEFORE,
|
||||
TIMERMACRO_MATCH,
|
||||
TIMERMACRO_AFTER,
|
||||
"",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *TimerFileMacros[] = {
|
||||
TIMERMACRO_TITLE,
|
||||
TIMERMACRO_EPISODE,
|
||||
"",
|
||||
NULL
|
||||
};
|
||||
|
||||
const cTimer *cMenuEditTimer::addedTimer = NULL;
|
||||
|
||||
cMenuEditTimer::cMenuEditTimer(cTimer *Timer, bool New)
|
||||
@ -1000,6 +1017,7 @@ cMenuEditTimer::cMenuEditTimer(cTimer *Timer, bool New)
|
||||
{
|
||||
SetMenuCategory(mcTimerEdit);
|
||||
addedTimer = NULL;
|
||||
pattern = NULL;
|
||||
file = NULL;
|
||||
day = firstday = NULL;
|
||||
timer = Timer;
|
||||
@ -1019,6 +1037,7 @@ cMenuEditTimer::cMenuEditTimer(cTimer *Timer, bool New)
|
||||
Add(new cMenuEditIntItem( tr("Lifetime"), &data.lifetime, 0, MAXLIFETIME));
|
||||
Add(file = new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file)));
|
||||
SetFirstDayItem();
|
||||
SetPatternItem(true);
|
||||
if (data.remote)
|
||||
strn0cpy(remote, data.remote, sizeof(remote));
|
||||
else
|
||||
@ -1047,7 +1066,7 @@ const cTimer *cMenuEditTimer::AddedTimer(void)
|
||||
|
||||
void cMenuEditTimer::SetHelpKeys(void)
|
||||
{
|
||||
SetHelp(tr("Button$Folder"), data.weekdays ? tr("Button$Single") : tr("Button$Repeating"));
|
||||
SetHelp(tr("Button$Folder"), data.weekdays ? tr("Button$Single") : tr("Button$Repeating"), *data.pattern ? tr("Button$Regular") : tr("Button$Pattern"));
|
||||
}
|
||||
|
||||
void cMenuEditTimer::SetFirstDayItem(void)
|
||||
@ -1063,6 +1082,40 @@ void cMenuEditTimer::SetFirstDayItem(void)
|
||||
}
|
||||
}
|
||||
|
||||
void cMenuEditTimer::SetPatternItem(bool Initial)
|
||||
{
|
||||
if (Initial && !*data.pattern) {
|
||||
file->SetMacros(TimerFileMacros);
|
||||
return;
|
||||
}
|
||||
if (!pattern) {
|
||||
if (data.HasFlags(tfRecording)) {
|
||||
Skins.Message(mtWarning, tr("Timer is recording!"));
|
||||
return;
|
||||
}
|
||||
if (!*data.pattern) {
|
||||
char *p = strrchr(data.file, FOLDERDELIMCHAR);
|
||||
if (p)
|
||||
p++;
|
||||
else
|
||||
p = data.file;
|
||||
strn0cpy(data.pattern, p, sizeof(data.pattern));
|
||||
}
|
||||
Ins(pattern = new cMenuEditStrItem( tr("Pattern"), data.pattern, sizeof(data.pattern)), true, file);
|
||||
pattern->SetKeepSpace();
|
||||
file->SetMacros(TimerFileMacrosForPattern);
|
||||
Display();
|
||||
}
|
||||
else {
|
||||
Del(pattern->Index());
|
||||
pattern = NULL;
|
||||
*data.pattern = 0;
|
||||
file->SetMacros(TimerFileMacros);
|
||||
Display();
|
||||
}
|
||||
SetHelpKeys();
|
||||
}
|
||||
|
||||
eOSState cMenuEditTimer::SetFolder(void)
|
||||
{
|
||||
if (cMenuFolder *mf = dynamic_cast<cMenuFolder *>(SubMenu())) {
|
||||
@ -1142,6 +1195,8 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
|
||||
cRecordControls::Stop(timer);
|
||||
if (timer->Remote() && data.Remote())
|
||||
Timers->SetSyncStateKey(StateKeySVDRPRemoteTimersPoll);
|
||||
if (data.Local() && !timer->IsPatternTimer() && data.IsPatternTimer())
|
||||
data.SetEvent(NULL);
|
||||
*timer = data;
|
||||
}
|
||||
LOCK_SCHEDULES_READ;
|
||||
@ -1159,7 +1214,8 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
|
||||
Display();
|
||||
}
|
||||
return osContinue;
|
||||
case kYellow:
|
||||
case kYellow: SetPatternItem();
|
||||
return osContinue;
|
||||
case kBlue: return osContinue;
|
||||
default: break;
|
||||
}
|
||||
@ -1212,12 +1268,19 @@ void cMenuTimerItem::Set(void)
|
||||
strftime(buffer, sizeof(buffer), "%Y%m%d", &tm_r);
|
||||
day = buffer;
|
||||
}
|
||||
const char *File = Setup.FoldersInTimerMenu ? NULL : strrchr(timer->File(), FOLDERDELIMCHAR);
|
||||
const char *File = timer->Pattern();
|
||||
if (!*File) {
|
||||
if (timer->HasFlags(tfSpawned) && timer->Event() && timer->Event()->Title())
|
||||
File = timer->Event()->Title();
|
||||
else {
|
||||
File = Setup.FoldersInTimerMenu ? NULL : strrchr(timer->File(), FOLDERDELIMCHAR);
|
||||
if (File && strcmp(File + 1, TIMERMACRO_TITLE) && strcmp(File + 1, TIMERMACRO_EPISODE))
|
||||
File++;
|
||||
else
|
||||
File = timer->File();
|
||||
SetText(cString::sprintf("%c\t%d\t%s%s%s\t%02d:%02d\t%02d:%02d\t%s%s",
|
||||
}
|
||||
}
|
||||
SetText(cString::sprintf("%c\t%d\t%s%s%s\t%02d:%02d\t%02d:%02d\t%s%s%s%s",
|
||||
!(timer->HasFlags(tfActive)) ? ' ' : timer->FirstDay() ? '!' : timer->Recording() ? '#' : '>',
|
||||
timer->Channel()->Number(),
|
||||
*name,
|
||||
@ -1228,7 +1291,9 @@ void cMenuTimerItem::Set(void)
|
||||
timer->Stop() / 100,
|
||||
timer->Stop() % 100,
|
||||
timer->Remote() ? *cString::sprintf("@%s: ", timer->Remote()) : "",
|
||||
File));
|
||||
timer->IsPatternTimer() ? "{" : "",
|
||||
File,
|
||||
timer->IsPatternTimer() ? "}" : ""));
|
||||
}
|
||||
|
||||
void cMenuTimerItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable)
|
||||
@ -1544,6 +1609,8 @@ bool cMenuScheduleItem::Update(const cTimers *Timers, bool Force)
|
||||
eTimerMatch OldTimerMatch = timerMatch;
|
||||
bool OldTimerActive = timerActive;
|
||||
const cTimer *Timer = Timers->GetMatch(event, &timerMatch);
|
||||
if (event->EndTime() < time(NULL) && !event->IsRunning())
|
||||
timerMatch = tmNone;
|
||||
timerActive = Timer && Timer->HasFlags(tfActive);
|
||||
if (Force || timerMatch != OldTimerMatch || timerActive != OldTimerActive) {
|
||||
cString buffer;
|
||||
@ -5354,8 +5421,13 @@ void cRecordControl::Stop(bool ExecuteUserCommand)
|
||||
bool cRecordControl::Process(time_t t)
|
||||
{
|
||||
if (!recorder || !recorder->IsAttached() || !timer || !timer->Matches(t)) {
|
||||
if (timer)
|
||||
if (timer) {
|
||||
timer->SetPending(false);
|
||||
if (timer->HasFlags(tfAvoid)) {
|
||||
const char *p = strgetlast(timer->File(), FOLDERDELIMCHAR);
|
||||
DoneRecordingsPattern.Append(p);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
4
menu.h
4
menu.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.h 4.8 2018/04/14 10:24:41 kls Exp $
|
||||
* $Id: menu.h 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __MENU_H
|
||||
@ -79,11 +79,13 @@ private:
|
||||
bool addIfConfirmed;
|
||||
cStringList svdrpServerNames;
|
||||
char remote[HOST_NAME_MAX];
|
||||
cMenuEditStrItem *pattern;
|
||||
cMenuEditStrItem *file;
|
||||
cMenuEditDateItem *day;
|
||||
cMenuEditDateItem *firstday;
|
||||
eOSState SetFolder(void);
|
||||
void SetFirstDayItem(void);
|
||||
void SetPatternItem(bool Initial = false);
|
||||
void SetHelpKeys(void);
|
||||
public:
|
||||
cMenuEditTimer(cTimer *Timer, bool New = false);
|
||||
|
51
menuitems.c
51
menuitems.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menuitems.c 4.3 2018/03/23 15:37:02 kls Exp $
|
||||
* $Id: menuitems.c 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menuitems.h"
|
||||
@ -390,6 +390,10 @@ cMenuEditStrItem::cMenuEditStrItem(const char *Name, char *Value, int Length, co
|
||||
allowed = Allowed ? Allowed : tr(FileNameChars);
|
||||
pos = -1;
|
||||
offset = 0;
|
||||
keepSpace = false;
|
||||
macro = -1;
|
||||
lastMacro = -1;
|
||||
macros = NULL;
|
||||
insert = uppercase = false;
|
||||
newchar = true;
|
||||
lengthUtf8 = 0;
|
||||
@ -408,6 +412,13 @@ cMenuEditStrItem::~cMenuEditStrItem()
|
||||
delete[] charMapUtf8;
|
||||
}
|
||||
|
||||
void cMenuEditStrItem::SetMacros(const char **Macros)
|
||||
{
|
||||
macros = Macros;
|
||||
macro = 0;
|
||||
lastMacro = -1;
|
||||
}
|
||||
|
||||
void cMenuEditStrItem::EnterEditMode(void)
|
||||
{
|
||||
if (!valueUtf8) {
|
||||
@ -430,6 +441,7 @@ void cMenuEditStrItem::LeaveEditMode(bool SaveValue)
|
||||
if (valueUtf8) {
|
||||
if (SaveValue) {
|
||||
Utf8FromArray(valueUtf8, value, length);
|
||||
if (!keepSpace)
|
||||
stripspace(value);
|
||||
}
|
||||
lengthUtf8 = 0;
|
||||
@ -448,7 +460,7 @@ void cMenuEditStrItem::LeaveEditMode(bool SaveValue)
|
||||
void cMenuEditStrItem::SetHelpKeys(void)
|
||||
{
|
||||
if (InEditMode())
|
||||
SetHelp(tr("Button$ABC/abc"), insert ? tr("Button$Overwrite") : tr("Button$Insert"), tr("Button$Delete"));
|
||||
SetHelp(tr("Button$ABC/abc"), insert ? tr("Button$Overwrite") : tr("Button$Insert"), tr("Button$Delete"), macros ? tr("Button$Macro") : NULL);
|
||||
else
|
||||
SetHelp(NULL);
|
||||
}
|
||||
@ -581,11 +593,39 @@ void cMenuEditStrItem::Delete(void)
|
||||
lengthUtf8--;
|
||||
}
|
||||
|
||||
void cMenuEditStrItem::InsertMacro(void)
|
||||
{
|
||||
if (!macros)
|
||||
return;
|
||||
if (lastMacro >= 0) {
|
||||
int l = strlen(macros[lastMacro]);
|
||||
while (l-- > 0)
|
||||
Delete();
|
||||
}
|
||||
const char *p = macros[macro];
|
||||
int oldPos = pos;
|
||||
bool oldInsert = insert;
|
||||
insert = true;
|
||||
newchar = true;
|
||||
while (*p) {
|
||||
Type(*p);
|
||||
p++;
|
||||
}
|
||||
insert = oldInsert;
|
||||
pos = oldPos;
|
||||
lastMacro = macro;
|
||||
if (!macros[++macro])
|
||||
macro = 0;
|
||||
}
|
||||
|
||||
eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
|
||||
{
|
||||
bool SameKey = NORMALKEY(Key) == lastKey;
|
||||
if (Key != kNone)
|
||||
if (Key != kNone) {
|
||||
lastKey = NORMALKEY(Key);
|
||||
if (Key != kBlue)
|
||||
lastMacro = -1;
|
||||
}
|
||||
else if (!newchar && k0 <= lastKey && lastKey <= k9 && autoAdvanceTimeout.TimedOut()) {
|
||||
AdvancePos();
|
||||
newchar = true;
|
||||
@ -635,8 +675,9 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
|
||||
return osUnknown;
|
||||
break;
|
||||
case kBlue|k_Repeat:
|
||||
case kBlue: // consume the key only if in edit-mode
|
||||
if (!InEditMode())
|
||||
case kBlue: if (InEditMode())
|
||||
InsertMacro();
|
||||
else
|
||||
return osUnknown;
|
||||
break;
|
||||
case kLeft|k_Repeat:
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menuitems.h 4.1 2015/09/06 10:38:37 kls Exp $
|
||||
* $Id: menuitems.h 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __MENUITEMS_H
|
||||
@ -111,6 +111,9 @@ private:
|
||||
int length;
|
||||
const char *allowed;
|
||||
int pos, offset;
|
||||
bool keepSpace;
|
||||
const char **macros;
|
||||
int macro, lastMacro;
|
||||
bool insert, newchar, uppercase;
|
||||
int lengthUtf8;
|
||||
uint *valueUtf8;
|
||||
@ -127,6 +130,7 @@ private:
|
||||
void Type(uint c);
|
||||
void Insert(void);
|
||||
void Delete(void);
|
||||
void InsertMacro(void);
|
||||
protected:
|
||||
void EnterEditMode(void);
|
||||
void LeaveEditMode(bool SaveValue = false);
|
||||
@ -134,6 +138,8 @@ protected:
|
||||
public:
|
||||
cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed = NULL);
|
||||
~cMenuEditStrItem();
|
||||
void SetKeepSpace(void) { keepSpace = true; }
|
||||
void SetMacros(const char **Macros);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
|
17
po/ar.po
17
po/ar.po
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2008-10-16 11:16-0400\n"
|
||||
"Last-Translator: Osama Alrawab <alrawab@hotmail.com>\n"
|
||||
"Language-Team: Arabic <ar@li.org>\n"
|
||||
@ -691,9 +691,21 @@ msgstr "Single"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Repeating"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "اليوم الاول"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1495,6 +1507,9 @@ msgstr "اعادة الكتابة"
|
||||
msgid "Button$Insert"
|
||||
msgstr "ادراج"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "الملحق"
|
||||
|
||||
|
17
po/ca_ES.po
17
po/ca_ES.po
@ -10,7 +10,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2008-03-02 19:02+0100\n"
|
||||
"Last-Translator: Luca Olivetti <luca@ventoso.org>\n"
|
||||
"Language-Team: Catalan <vdr@linuxtv.org>\n"
|
||||
@ -690,9 +690,21 @@ msgstr "Individual"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Repetitiu"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Primer dia"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1494,6 +1506,9 @@ msgstr "Sobrescriure"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Inserir"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Plugin"
|
||||
|
||||
|
17
po/cs_CZ.po
17
po/cs_CZ.po
@ -10,7 +10,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2010-05-06 11:00+0200\n"
|
||||
"Last-Translator: Aleš Juřík <ajurik@quick.cz>\n"
|
||||
"Language-Team: Czech <vdr@linuxtv.org>\n"
|
||||
@ -690,9 +690,21 @@ msgstr "Bez opakování"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "S opakováním"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "První den"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1494,6 +1506,9 @@ msgstr "Přepsat"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Vložit"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Modul"
|
||||
|
||||
|
17
po/da_DK.po
17
po/da_DK.po
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2007-08-12 14:17+0200\n"
|
||||
"Last-Translator: Mogens Elneff <mogens@elneff.dk>\n"
|
||||
"Language-Team: Danish <vdr@linuxtv.org>\n"
|
||||
@ -687,9 +687,21 @@ msgstr ""
|
||||
msgid "Button$Repeating"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Første dag"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1491,6 +1503,9 @@ msgstr "Overskriv"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Indsæt"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Plugin"
|
||||
|
||||
|
17
po/de_DE.po
17
po/de_DE.po
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2015-02-10 13:45+0100\n"
|
||||
"Last-Translator: Klaus Schmidinger <vdr@tvdr.de>\n"
|
||||
"Language-Team: German <vdr@linuxtv.org>\n"
|
||||
@ -688,9 +688,21 @@ msgstr "Einmalig"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Wiederholend"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr "Normal"
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr "Muster"
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Erster Tag"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr "Timer nimmt auf!"
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr "Muster"
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr "Fehler beim Ansprechen des fernen Timers"
|
||||
|
||||
@ -1492,6 +1504,9 @@ msgstr "
|
||||
msgid "Button$Insert"
|
||||
msgstr "Einfügen"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr "Makro"
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Plugin"
|
||||
|
||||
|
17
po/el_GR.po
17
po/el_GR.po
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2007-08-12 14:17+0200\n"
|
||||
"Last-Translator: Dimitrios Dimitrakos <mail@dimitrios.de>\n"
|
||||
"Language-Team: Greek <vdr@linuxtv.org>\n"
|
||||
@ -687,9 +687,21 @@ msgstr ""
|
||||
msgid "Button$Repeating"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Ðñþôç ìÝñá"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1491,6 +1503,9 @@ msgstr "
|
||||
msgid "Button$Insert"
|
||||
msgstr "ÅéóáãùãÞ"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "ÅðÝêôáóç"
|
||||
|
||||
|
17
po/es_ES.po
17
po/es_ES.po
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2015-02-19 23:00+0100\n"
|
||||
"Last-Translator: Gabriel Bonich <gbonich@gmail.com>\n"
|
||||
"Language-Team: Spanish <vdr@linuxtv.org>\n"
|
||||
@ -688,9 +688,21 @@ msgstr "Individual"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Periódico"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Primer día"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1492,6 +1504,9 @@ msgstr "Sobreescribir"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Insertar"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Plugin"
|
||||
|
||||
|
17
po/et_EE.po
17
po/et_EE.po
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2007-08-12 14:17+0200\n"
|
||||
"Last-Translator: Arthur Konovalov <artlov@gmail.com>\n"
|
||||
"Language-Team: Estonian <vdr@linuxtv.org>\n"
|
||||
@ -687,9 +687,21 @@ msgstr "Üksik"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Korduv"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "1. päev"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr "Kaugtaimeri viga"
|
||||
|
||||
@ -1491,6 +1503,9 @@ msgstr "Asenda (OVR)"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Lisa (INS)"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Plugin"
|
||||
|
||||
|
17
po/fi_FI.po
17
po/fi_FI.po
@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2007-08-15 15:52+0200\n"
|
||||
"Last-Translator: Matti Lehtimäki <matti.lehtimaki@gmail.com>\n"
|
||||
"Language-Team: Finnish <vdr@linuxtv.org>\n"
|
||||
@ -691,9 +691,21 @@ msgstr "Yksittäinen"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Toistuva"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "1. päivä"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr "Etäajastimen hakeminen epäonnistui"
|
||||
|
||||
@ -1495,6 +1507,9 @@ msgstr "Korvaa"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Lisää"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Laajennos"
|
||||
|
||||
|
17
po/fr_FR.po
17
po/fr_FR.po
@ -18,7 +18,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2018-04-14 10:16+0100\n"
|
||||
"Last-Translator: Bernard Jaulin <bernard.jaulin@gmail.com>\n"
|
||||
"Language-Team: French <vdr@linuxtv.org>\n"
|
||||
@ -698,9 +698,21 @@ msgstr "Simple"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Périodique"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Premier jour"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr "Erreur pendant l'accès à la programmation"
|
||||
|
||||
@ -1502,6 +1514,9 @@ msgstr "Écraser"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Insérer"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Module"
|
||||
|
||||
|
17
po/hr_HR.po
17
po/hr_HR.po
@ -9,7 +9,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2008-03-17 19:00+0100\n"
|
||||
"Last-Translator: Adrian Caval <anrxc@sysphere.org>\n"
|
||||
"Language-Team: Croatian <vdr@linuxtv.org>\n"
|
||||
@ -689,9 +689,21 @@ msgstr ""
|
||||
msgid "Button$Repeating"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Prvi dan"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1493,6 +1505,9 @@ msgstr "Prepi
|
||||
msgid "Button$Insert"
|
||||
msgstr "Umetni"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Dodatak"
|
||||
|
||||
|
17
po/hu_HU.po
17
po/hu_HU.po
@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2018-04-09 21:42+0300\n"
|
||||
"Last-Translator: István Füley <ifuley@tigercomp.ro>\n"
|
||||
"Language-Team: Hungarian <vdr@linuxtv.org>\n"
|
||||
@ -692,9 +692,21 @@ msgstr "Egyszeri"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Ismétlődő"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Első nap"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr "Távoli időzítő nem elérhető"
|
||||
|
||||
@ -1496,6 +1508,9 @@ msgstr "Felülírás"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Beillesztés"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Plugin"
|
||||
|
||||
|
17
po/it_IT.po
17
po/it_IT.po
@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2018-04-06 19:13+0100\n"
|
||||
"Last-Translator: Gringo <vdr-italian@tiscali.it>\n"
|
||||
"Language-Team: Italian <vdr@linuxtv.org>\n"
|
||||
@ -693,9 +693,21 @@ msgstr "Una volta"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Repliche"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "1° giorno"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr "Errore durante l'accesso al timer remoto"
|
||||
|
||||
@ -1497,6 +1509,9 @@ msgstr "Sovrascrivi"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Inserisci"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Plugin"
|
||||
|
||||
|
17
po/lt_LT.po
17
po/lt_LT.po
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2015-02-11 14:02+0200\n"
|
||||
"Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n"
|
||||
"Language-Team: Lithuanian <vdr@linuxtv.org>\n"
|
||||
@ -687,9 +687,21 @@ msgstr "Vienas"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Kartotinas"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Pirma diena"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1491,6 +1503,9 @@ msgstr "Perrąšyti"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Įterpti"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Įskiepas"
|
||||
|
||||
|
17
po/mk_MK.po
17
po/mk_MK.po
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2018-03-31 21:47+0100\n"
|
||||
"Last-Translator: Dimitar Petrovski <dimeptr@gmail.com>\n"
|
||||
"Language-Team: Macedonian <kde-i18n-doc@kde.org>\n"
|
||||
@ -689,9 +689,21 @@ msgstr "Единчен"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Периодичен"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Прв ден"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr "Грешка при пристап на далечен тајмер"
|
||||
|
||||
@ -1493,6 +1505,9 @@ msgstr "Препиши"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Вметни"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Додаток"
|
||||
|
||||
|
17
po/nl_NL.po
17
po/nl_NL.po
@ -13,7 +13,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2015-02-10 19:43+0100\n"
|
||||
"Last-Translator: Erik Oomen <oomen.e@gmail.com>\n"
|
||||
"Language-Team: Dutch <vdr@linuxtv.org>\n"
|
||||
@ -693,9 +693,21 @@ msgstr "Eenmalig"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Herhalen"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Eerste dag"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1497,6 +1509,9 @@ msgstr "Overschrijven"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Invoegen"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Plugin"
|
||||
|
||||
|
17
po/nn_NO.po
17
po/nn_NO.po
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2007-08-12 14:17+0200\n"
|
||||
"Last-Translator: Truls Slevigen <truls@slevigen.no>\n"
|
||||
"Language-Team: Norwegian Nynorsk <vdr@linuxtv.org>\n"
|
||||
@ -688,9 +688,21 @@ msgstr ""
|
||||
msgid "Button$Repeating"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Første dag"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1492,6 +1504,9 @@ msgstr ""
|
||||
msgid "Button$Insert"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Plugin"
|
||||
|
||||
|
17
po/pl_PL.po
17
po/pl_PL.po
@ -10,7 +10,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2018-02-19 00:42+0100\n"
|
||||
"Last-Translator: Tomasz Maciej Nowak <tmn505@gmail.com>\n"
|
||||
"Language-Team: Polish <vdr@linuxtv.org>\n"
|
||||
@ -692,9 +692,21 @@ msgstr "Pojedynczy"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Powtarzanie"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Pierwszy dzień"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr "Błąd podczas dostępu do zdalnego timera"
|
||||
|
||||
@ -1496,6 +1508,9 @@ msgstr "Nadpisz"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Wstaw"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Wtyczka"
|
||||
|
||||
|
17
po/pt_PT.po
17
po/pt_PT.po
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2010-03-28 22:49+0100\n"
|
||||
"Last-Translator: Cris Silva <hudokkow@gmail.com>\n"
|
||||
"Language-Team: Portuguese <vdr@linuxtv.org>\n"
|
||||
@ -688,9 +688,21 @@ msgstr ""
|
||||
msgid "Button$Repeating"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "1° dia"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1492,6 +1504,9 @@ msgstr "Sobrescrever"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Inserir"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Plugin"
|
||||
|
||||
|
17
po/ro_RO.po
17
po/ro_RO.po
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2015-02-11 22:26+0100\n"
|
||||
"Last-Translator: Lucian Muresan <lucianm@users.sourceforge.net>\n"
|
||||
"Language-Team: Romanian <vdr@linuxtv.org>\n"
|
||||
@ -689,9 +689,21 @@ msgstr "Odată"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Repetitiv"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Prima zi"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1493,6 +1505,9 @@ msgstr "Suprascrie"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Inserează"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Plugin"
|
||||
|
||||
|
17
po/ru_RU.po
17
po/ru_RU.po
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2016-12-27 17:13+0100\n"
|
||||
"Last-Translator: Pridvorov Andrey <ua0lnj@bk.ru>\n"
|
||||
"Language-Team: Russian <vdr@linuxtv.org>\n"
|
||||
@ -688,9 +688,21 @@ msgstr "Один раз"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Повтор"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Первый день"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr "Ошибка доступа к таймеру"
|
||||
|
||||
@ -1492,6 +1504,9 @@ msgstr "Замена"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Вставка"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Модуль"
|
||||
|
||||
|
17
po/sk_SK.po
17
po/sk_SK.po
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2015-02-17 18:59+0100\n"
|
||||
"Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n"
|
||||
"Language-Team: Slovak <vdr@linuxtv.org>\n"
|
||||
@ -688,9 +688,21 @@ msgstr "bez opakovania"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "s opakovaním"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Odo dòa"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1492,6 +1504,9 @@ msgstr "Prep
|
||||
msgid "Button$Insert"
|
||||
msgstr "Vlo¾i»"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Modul"
|
||||
|
||||
|
17
po/sl_SI.po
17
po/sl_SI.po
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2013-03-04 12:46+0100\n"
|
||||
"Last-Translator: Matjaz Thaler <matjaz.thaler@guest.arnes.si>\n"
|
||||
"Language-Team: Slovenian <vdr@linuxtv.org>\n"
|
||||
@ -688,9 +688,21 @@ msgstr "Enkraten"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Ponavljajoèe"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Prvi dan"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1492,6 +1504,9 @@ msgstr "Prepi
|
||||
msgid "Button$Insert"
|
||||
msgstr "Vstavi"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Vstavek"
|
||||
|
||||
|
17
po/sr_RS.po
17
po/sr_RS.po
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2013-03-16 15:05+0100\n"
|
||||
"Last-Translator: Zoran Turalija <zoran.turalija@gmail.com>\n"
|
||||
"Language-Team: Serbian <vdr@linuxtv.org>\n"
|
||||
@ -688,9 +688,21 @@ msgstr "Jedinstven"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Ponavljajuæi"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Prvi dan"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1492,6 +1504,9 @@ msgstr "Zameni"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Ubaci"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Dodatak"
|
||||
|
||||
|
17
po/sv_SE.po
17
po/sv_SE.po
@ -12,7 +12,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2015-02-12 21:58+0100\n"
|
||||
"Last-Translator: Magnus Sirviö <sirwio@hotmail.com>\n"
|
||||
"Language-Team: Swedish <vdr@linuxtv.org>\n"
|
||||
@ -692,9 +692,21 @@ msgstr "Enskilld"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Repeterande"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Första dag"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1496,6 +1508,9 @@ msgstr "Skriv
|
||||
msgid "Button$Insert"
|
||||
msgstr "Infoga"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Modul"
|
||||
|
||||
|
17
po/tr_TR.po
17
po/tr_TR.po
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2008-02-28 00:33+0100\n"
|
||||
"Last-Translator: Oktay Yolgeçen <oktay_73@yahoo.de>\n"
|
||||
"Language-Team: Turkish <vdr@linuxtv.org>\n"
|
||||
@ -687,9 +687,21 @@ msgstr ""
|
||||
msgid "Button$Repeating"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Ýlk gün"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1491,6 +1503,9 @@ msgstr "
|
||||
msgid "Button$Insert"
|
||||
msgstr "Ekle"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Eklenti"
|
||||
|
||||
|
17
po/uk_UA.po
17
po/uk_UA.po
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2018-03-18 20:00+0100\n"
|
||||
"Last-Translator: Yarema aka Knedlyk <yupadmin@gmail.com>\n"
|
||||
"Language-Team: Ukrainian <vdr@linuxtv.org>\n"
|
||||
@ -688,9 +688,21 @@ msgstr "Одинарне"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "Повтор"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "Перший день"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr "Помилка доступу до віддаленого таймера"
|
||||
|
||||
@ -1492,6 +1504,9 @@ msgstr "Заміна"
|
||||
msgid "Button$Insert"
|
||||
msgstr "Вставка"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "Модуль"
|
||||
|
||||
|
17
po/zh_CN.po
17
po/zh_CN.po
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: VDR 2.4.0\n"
|
||||
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
|
||||
"POT-Creation-Date: 2020-06-15 17:50+0200\n"
|
||||
"POT-Creation-Date: 2020-12-24 17:42+0100\n"
|
||||
"PO-Revision-Date: 2013-03-04 14:52+0800\n"
|
||||
"Last-Translator: NFVDR <nfvdr@live.com>\n"
|
||||
"Language-Team: Chinese (simplified) <nfvdr@live.com>\n"
|
||||
@ -689,9 +689,21 @@ msgstr "单个"
|
||||
msgid "Button$Repeating"
|
||||
msgstr "重复"
|
||||
|
||||
msgid "Button$Regular"
|
||||
msgstr ""
|
||||
|
||||
msgid "Button$Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "First day"
|
||||
msgstr "第一天"
|
||||
|
||||
msgid "Timer is recording!"
|
||||
msgstr ""
|
||||
|
||||
msgid "Pattern"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error while accessing remote timer"
|
||||
msgstr ""
|
||||
|
||||
@ -1493,6 +1505,9 @@ msgstr "覆盖"
|
||||
msgid "Button$Insert"
|
||||
msgstr "插入"
|
||||
|
||||
msgid "Button$Macro"
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugin"
|
||||
msgstr "插件"
|
||||
|
||||
|
70
recording.c
70
recording.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: recording.c 4.29 2020/10/30 16:08:29 kls Exp $
|
||||
* $Id: recording.c 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#include "recording.h"
|
||||
@ -3050,6 +3050,74 @@ cUnbufferedFile *cFileName::NextFile(void)
|
||||
return SetOffset(fileNumber + 1);
|
||||
}
|
||||
|
||||
// --- cDoneRecordings -------------------------------------------------------
|
||||
|
||||
cDoneRecordings DoneRecordingsPattern;
|
||||
|
||||
bool cDoneRecordings::Load(const char *FileName)
|
||||
{
|
||||
fileName = FileName;
|
||||
if (*fileName && access(fileName, F_OK) == 0) {
|
||||
isyslog("loading %s", *fileName);
|
||||
FILE *f = fopen(fileName, "r");
|
||||
if (f) {
|
||||
char *s;
|
||||
cReadLine ReadLine;
|
||||
while ((s = ReadLine.Read(f)) != NULL)
|
||||
Add(s);
|
||||
fclose(f);
|
||||
}
|
||||
else {
|
||||
LOG_ERROR_STR(*fileName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cDoneRecordings::Save(void) const
|
||||
{
|
||||
bool result = true;
|
||||
cSafeFile f(fileName);
|
||||
if (f.Open()) {
|
||||
for (int i = 0; i < doneRecordings.Size(); i++) {
|
||||
if (fputs(doneRecordings[i], f) == EOF || fputc('\n', f) == EOF) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!f.Close())
|
||||
result = false;
|
||||
}
|
||||
else
|
||||
result = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
void cDoneRecordings::Add(const char *Title)
|
||||
{
|
||||
doneRecordings.Append(strdup(Title));
|
||||
}
|
||||
|
||||
void cDoneRecordings::Append(const char *Title)
|
||||
{
|
||||
if (!Contains(Title)) {
|
||||
Add(Title);
|
||||
if (FILE *f = fopen(fileName, "a")) {
|
||||
fputs(Title, f);
|
||||
fputc('\n', f);
|
||||
fclose(f);
|
||||
}
|
||||
else
|
||||
esyslog("ERROR: can't open '%s' for appending '%s'", *fileName, Title);
|
||||
}
|
||||
}
|
||||
|
||||
bool cDoneRecordings::Contains(const char *Title) const
|
||||
{
|
||||
return doneRecordings.Find(Title) >= 0;
|
||||
}
|
||||
|
||||
// --- Index stuff -----------------------------------------------------------
|
||||
|
||||
cString IndexToHMSF(int Index, bool WithFrame, double FramesPerSecond)
|
||||
|
16
recording.h
16
recording.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: recording.h 4.10 2020/09/16 13:48:33 kls Exp $
|
||||
* $Id: recording.h 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __RECORDING_H
|
||||
@ -504,6 +504,20 @@ public:
|
||||
cUnbufferedFile *NextFile(void);
|
||||
};
|
||||
|
||||
class cDoneRecordings {
|
||||
private:
|
||||
cString fileName;
|
||||
cStringList doneRecordings;
|
||||
void Add(const char *Title);
|
||||
public:
|
||||
bool Load(const char *FileName);
|
||||
bool Save(void) const;
|
||||
void Append(const char *Title);
|
||||
bool Contains(const char *Title) const;
|
||||
};
|
||||
|
||||
extern cDoneRecordings DoneRecordingsPattern;
|
||||
|
||||
cString IndexToHMSF(int Index, bool WithFrame = false, double FramesPerSecond = DEFAULTFRAMESPERSECOND);
|
||||
// Converts the given index to a string, optionally containing the frame number.
|
||||
int HMSFToIndex(const char *HMSF, double FramesPerSecond = DEFAULTFRAMESPERSECOND);
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: skinlcars.c 4.7 2020/05/18 16:47:29 kls Exp $
|
||||
* $Id: skinlcars.c 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
// "Star Trek: The Next Generation"(R) is a registered trademark of Paramount Pictures,
|
||||
@ -1264,7 +1264,9 @@ void cSkinLCARSDisplayMenu::DrawTimers(void)
|
||||
if (y + lineHeight > ys05)
|
||||
break;
|
||||
if (const cTimer *Timer = SortedTimers[i]) {
|
||||
if (Timer->Recording()) {
|
||||
if (Timer->IsPatternTimer())
|
||||
SortedTimers[i] = NULL;
|
||||
else if (Timer->Recording()) {
|
||||
if (Timer->Remote()) {
|
||||
if (!Device && Timer->HasFlags(tfActive)) {
|
||||
DrawTimer(Timer, y, false);
|
||||
|
8
svdrp.c
8
svdrp.c
@ -10,7 +10,7 @@
|
||||
* and interact with the Video Disk Recorder - or write a full featured
|
||||
* graphical interface that sits on top of an SVDRP connection.
|
||||
*
|
||||
* $Id: svdrp.c 4.43 2020/06/22 20:59:49 kls Exp $
|
||||
* $Id: svdrp.c 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#include "svdrp.h"
|
||||
@ -2048,6 +2048,10 @@ void cSVDRPServer::CmdMODT(const char *Option)
|
||||
Reply(501, "Error in timer settings");
|
||||
return;
|
||||
}
|
||||
if (IsRecording && t.IsPatternTimer()) {
|
||||
Reply(550, "Timer is recording");
|
||||
return;
|
||||
}
|
||||
*Timer = t;
|
||||
if (IsRecording)
|
||||
Timer->SetFlags(tfRecording);
|
||||
@ -2055,6 +2059,8 @@ void cSVDRPServer::CmdMODT(const char *Option)
|
||||
Timer->ClrFlags(tfRecording);
|
||||
Timers->SetModified();
|
||||
isyslog("SVDRP %s < %s modified timer %s (%s)", Setup.SVDRPHostName, *clientName, *Timer->ToDescr(), Timer->HasFlags(tfActive) ? "active" : "inactive");
|
||||
if (Timer->IsPatternTimer())
|
||||
Timer->SetEvent(NULL);
|
||||
Reply(250, "%d %s", Timer->Id(), *Timer->ToText(true));
|
||||
}
|
||||
else
|
||||
|
244
timers.c
244
timers.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: timers.c 4.20 2020/09/16 13:48:33 kls Exp $
|
||||
* $Id: timers.c 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#include "timers.h"
|
||||
@ -31,6 +31,7 @@ cTimer::cTimer(bool Instant, bool Pause, const cChannel *Channel)
|
||||
deferred = 0;
|
||||
pending = inVpsMargin = false;
|
||||
flags = tfNone;
|
||||
*pattern = 0;
|
||||
*file = 0;
|
||||
aux = NULL;
|
||||
remote = NULL;
|
||||
@ -81,7 +82,94 @@ cTimer::cTimer(bool Instant, bool Pause, const cChannel *Channel)
|
||||
snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : channel->Name());
|
||||
}
|
||||
|
||||
cTimer::cTimer(const cEvent *Event)
|
||||
static bool MatchPattern(const char *Pattern, const char *Title, cString *Before = NULL, cString *Match = NULL, cString *After = NULL)
|
||||
{
|
||||
if (Title) {
|
||||
bool AvoidDuplicates = startswith(Pattern, TIMERPATTERN_AVOID);
|
||||
if (AvoidDuplicates)
|
||||
Pattern++;
|
||||
if (strcmp(Pattern, "*") == 0) {
|
||||
if (Before)
|
||||
*Before = "";
|
||||
if (Match)
|
||||
*Match = Title;
|
||||
if (After)
|
||||
*After = "";
|
||||
return true;
|
||||
}
|
||||
bool AnchorBegin = startswith(Pattern, TIMERPATTERN_BEGIN);
|
||||
if (AnchorBegin)
|
||||
Pattern++;
|
||||
bool AnchorEnd = endswith(Pattern, TIMERPATTERN_END);
|
||||
cNullTerminate nt;
|
||||
if (AnchorEnd)
|
||||
nt.Set(const_cast<char *>(Pattern + strlen(Pattern) - 1));
|
||||
if (AnchorBegin && AnchorEnd) {
|
||||
if (strcmp(Title, Pattern) == 0) {
|
||||
if (Before)
|
||||
*Before = "";
|
||||
if (Match)
|
||||
*Match = Title;
|
||||
if (After)
|
||||
*After = "";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (AnchorBegin) {
|
||||
if (strstr(Title, Pattern) == Title) {
|
||||
if (Before)
|
||||
*Before = "";
|
||||
if (Match)
|
||||
*Match = Pattern;
|
||||
if (After)
|
||||
*After = cString(Title + strlen(Pattern));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (AnchorEnd) {
|
||||
if (endswith(Title, Pattern)) {
|
||||
if (Before)
|
||||
*Before = cString(Title, Title + strlen(Title) - strlen(Pattern));
|
||||
if (Match)
|
||||
*Match = Pattern;
|
||||
if (After)
|
||||
*After = "";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (const char *p = strstr(Title, Pattern)) {
|
||||
if (Before)
|
||||
*Before = cString(Title, p);
|
||||
if (Match)
|
||||
*Match = Pattern;
|
||||
if (After)
|
||||
*After = cString(p + strlen(Pattern));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static cString MakePatternFileName(const char *Pattern, const char *Title, const char *Episode, const char *File)
|
||||
{
|
||||
if (!Pattern || !Title || !File)
|
||||
return NULL;
|
||||
cString Before = "";
|
||||
cString Match = "";
|
||||
cString After = "";
|
||||
if (MatchPattern(Pattern, Title, &Before, &Match, &After)) {
|
||||
char *Result = strdup(File);
|
||||
Result = strreplace(Result, TIMERMACRO_TITLE, Title);
|
||||
Result = strreplace(Result, TIMERMACRO_EPISODE, Episode);
|
||||
Result = strreplace(Result, TIMERMACRO_BEFORE, Before);
|
||||
Result = strreplace(Result, TIMERMACRO_MATCH, Match);
|
||||
Result = strreplace(Result, TIMERMACRO_AFTER, After);
|
||||
return cString(Result, true);;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cTimer::cTimer(const cEvent *Event, const char *FileName, const cTimer *PatternTimer)
|
||||
{
|
||||
id = 0;
|
||||
startTime = stopTime = 0;
|
||||
@ -89,12 +177,15 @@ cTimer::cTimer(const cEvent *Event)
|
||||
deferred = 0;
|
||||
pending = inVpsMargin = false;
|
||||
flags = tfActive;
|
||||
*pattern = 0;
|
||||
*file = 0;
|
||||
aux = NULL;
|
||||
remote = NULL;
|
||||
event = NULL;
|
||||
if (!PatternTimer || PatternTimer->HasFlags(tfVps)) {
|
||||
if (Event->Vps() && Setup.UseVps)
|
||||
SetFlags(tfVps);
|
||||
}
|
||||
LOCK_CHANNELS_READ;
|
||||
channel = Channels->GetByChannelID(Event->ChannelID(), true);
|
||||
time_t tstart = (flags & tfVps) ? Event->Vps() : Event->StartTime();
|
||||
@ -112,11 +203,12 @@ cTimer::cTimer(const cEvent *Event)
|
||||
stop = time->tm_hour * 100 + time->tm_min;
|
||||
if (stop >= 2400)
|
||||
stop -= 2400;
|
||||
priority = Setup.DefaultPriority;
|
||||
lifetime = Setup.DefaultLifetime;
|
||||
const char *Title = Event->Title();
|
||||
if (!isempty(Title))
|
||||
Utf8Strn0Cpy(file, Event->Title(), sizeof(file));
|
||||
priority = PatternTimer ? PatternTimer->Priority() : Setup.DefaultPriority;
|
||||
lifetime = PatternTimer ? PatternTimer->Lifetime() : Setup.DefaultLifetime;
|
||||
if (!FileName)
|
||||
FileName = Event->Title();
|
||||
if (!isempty(FileName))
|
||||
Utf8Strn0Cpy(file, FileName, sizeof(file));
|
||||
SetEvent(Event);
|
||||
}
|
||||
|
||||
@ -156,6 +248,7 @@ cTimer& cTimer::operator= (const cTimer &Timer)
|
||||
stop = Timer.stop;
|
||||
priority = Timer.priority;
|
||||
lifetime = Timer.lifetime;
|
||||
strncpy(pattern, Timer.pattern, sizeof(pattern));
|
||||
strncpy(file, Timer.file, sizeof(file));
|
||||
free(aux);
|
||||
aux = Timer.aux ? strdup(Timer.aux) : NULL;
|
||||
@ -178,20 +271,37 @@ int cTimer::Compare(const cListObject &ListObject) const
|
||||
int r = t1 - t2;
|
||||
if (r == 0)
|
||||
r = ti->priority - priority;
|
||||
if (IsPatternTimer() ^ ti->IsPatternTimer()) {
|
||||
if (IsPatternTimer())
|
||||
r = 1;
|
||||
else
|
||||
r = -1;
|
||||
}
|
||||
else if (IsPatternTimer() && ti->IsPatternTimer())
|
||||
r = strcoll(Pattern(), ti->Pattern());
|
||||
return r;
|
||||
}
|
||||
|
||||
cString cTimer::PatternAndFile(void) const
|
||||
{
|
||||
if (IsPatternTimer())
|
||||
return cString::sprintf("{%s}%s", pattern, file);
|
||||
return file;
|
||||
}
|
||||
|
||||
cString cTimer::ToText(bool UseChannelID) const
|
||||
{
|
||||
strreplace(pattern, ':', '|');
|
||||
strreplace(file, ':', '|');
|
||||
cString buffer = cString::sprintf("%u:%s:%s:%04d:%04d:%d:%d:%s:%s", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, weekdays, true), start, stop, priority, lifetime, file, aux ? aux : "");
|
||||
cString buffer = cString::sprintf("%u:%s:%s:%04d:%04d:%d:%d:%s:%s", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, weekdays, true), start, stop, priority, lifetime, *PatternAndFile(), aux ? aux : "");
|
||||
strreplace(pattern, '|', ':');
|
||||
strreplace(file, '|', ':');
|
||||
return buffer;
|
||||
}
|
||||
|
||||
cString cTimer::ToDescr(void) const
|
||||
{
|
||||
return cString::sprintf("%d%s%s (%d %04d-%04d %s'%s')", Id(), remote ? "@" : "", remote ? remote : "", Channel()->Number(), start, stop, HasFlags(tfVps) ? "VPS " : "", file);
|
||||
return cString::sprintf("%d%s%s (%d %04d-%04d %s'%s')", Id(), remote ? "@" : "", remote ? remote : "", Channel()->Number(), start, stop, HasFlags(tfVps) ? "VPS " : "", *PatternAndFile());
|
||||
}
|
||||
|
||||
int cTimer::TimeToInt(int t)
|
||||
@ -332,7 +442,18 @@ bool cTimer::Parse(const char *s)
|
||||
}
|
||||
//TODO add more plausibility checks
|
||||
result = ParseDay(daybuffer, day, weekdays);
|
||||
Utf8Strn0Cpy(file, filebuffer, sizeof(file));
|
||||
char *fb = filebuffer;
|
||||
if (*fb == '{') {
|
||||
if (char *p = strchr(fb, '}')) {
|
||||
*p = 0;
|
||||
Utf8Strn0Cpy(pattern, fb + 1, sizeof(pattern));
|
||||
strreplace(pattern, '|', ':');
|
||||
fb = p + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
*pattern = 0;
|
||||
Utf8Strn0Cpy(file, fb, sizeof(file));
|
||||
strreplace(file, '|', ':');
|
||||
LOCK_CHANNELS_READ;
|
||||
if (isnumber(channelbuffer))
|
||||
@ -404,6 +525,11 @@ time_t cTimer::SetTime(time_t t, int SecondsFromMidnight)
|
||||
return mktime(&tm);
|
||||
}
|
||||
|
||||
void cTimer::SetPattern(const char *Pattern)
|
||||
{
|
||||
Utf8Strn0Cpy(pattern, Pattern, sizeof(pattern));
|
||||
}
|
||||
|
||||
void cTimer::SetFile(const char *File)
|
||||
{
|
||||
if (!isempty(File))
|
||||
@ -451,6 +577,9 @@ bool cTimer::Matches(time_t t, bool Directly, int Margin) const
|
||||
day = 0;
|
||||
}
|
||||
|
||||
if (IsPatternTimer())
|
||||
return false; // we only need to have start/stopTime initialized
|
||||
|
||||
if (t < deferred)
|
||||
return false;
|
||||
deferred = 0;
|
||||
@ -483,6 +612,21 @@ eTimerMatch cTimer::Matches(const cEvent *Event, int *Overlap) const
|
||||
// gets 200 added to the FULLMATCH.
|
||||
if (channel->GetChannelID() == Event->ChannelID()) {
|
||||
bool UseVps = HasFlags(tfVps) && Event->Vps();
|
||||
if (IsPatternTimer()) {
|
||||
if (startswith(Pattern(), TIMERPATTERN_AVOID)) {
|
||||
cString FileName = MakePatternFileName(Pattern(), Event->Title(), Event->ShortText(), File());
|
||||
if (*FileName) {
|
||||
const char *p = strgetlast(*FileName, FOLDERDELIMCHAR);
|
||||
if (DoneRecordingsPattern.Contains(p))
|
||||
return tmNone;
|
||||
}
|
||||
else
|
||||
return tmNone;
|
||||
}
|
||||
else if (!MatchPattern(Pattern(), Event->Title()))
|
||||
return tmNone;
|
||||
UseVps = false;
|
||||
}
|
||||
Matches(UseVps ? Event->Vps() : Event->StartTime(), true);
|
||||
int overlap = 0;
|
||||
if (UseVps) {
|
||||
@ -499,8 +643,11 @@ eTimerMatch cTimer::Matches(const cEvent *Event, int *Overlap) const
|
||||
overlap = FULLMATCH;
|
||||
else if (stopTime <= Event->StartTime() || Event->EndTime() <= startTime)
|
||||
overlap = 0;
|
||||
else
|
||||
else {
|
||||
overlap = (min(stopTime, Event->EndTime()) - max(startTime, Event->StartTime())) * FULLMATCH / max(Event->Duration(), 1);
|
||||
if (IsPatternTimer() && overlap > 0)
|
||||
overlap = FULLMATCH;
|
||||
}
|
||||
}
|
||||
startTime = stopTime = 0;
|
||||
if (Overlap)
|
||||
@ -542,8 +689,60 @@ void cTimer::SetId(int Id)
|
||||
id = Id;
|
||||
}
|
||||
|
||||
void cTimer::SpawnPatternTimer(const cEvent *Event, cTimers *Timers)
|
||||
{
|
||||
cString FileName = MakePatternFileName(Pattern(), Event->Title(), Event->ShortText(), File());
|
||||
isyslog("spawning timer %s for event %s", *ToDescr(), *Event->ToDescr());
|
||||
cTimer *t = new cTimer(Event, FileName, this);
|
||||
t->SetFlags(tfSpawned);
|
||||
if (startswith(Pattern(), TIMERPATTERN_AVOID))
|
||||
t->SetFlags(tfAvoid);
|
||||
Timers->Add(t);
|
||||
HandleRemoteTimerModifications(t);
|
||||
}
|
||||
|
||||
bool cTimer::SpawnPatternTimers(const cSchedules *Schedules, cTimers *Timers)
|
||||
{
|
||||
bool TimersSpawned = false;
|
||||
const cSchedule *Schedule = Schedules->GetSchedule(Channel());
|
||||
if (Schedule && Schedule->Events()->First()) {
|
||||
if (Schedule->Modified(scheduleState)) {
|
||||
time_t Now = time(NULL);
|
||||
for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) {
|
||||
if (Matches(e) != tmNone) {
|
||||
bool CheckThis = false;
|
||||
bool CheckNext = false;
|
||||
if (e->HasTimer()) // a matching event that already has a timer
|
||||
CheckNext = true;
|
||||
else if (e->EndTime() > Now) { // only look at events that have not yet ended
|
||||
CheckThis = true;
|
||||
CheckNext = true;
|
||||
}
|
||||
if (CheckThis) {
|
||||
SpawnPatternTimer(e, Timers);
|
||||
TimersSpawned = true;
|
||||
}
|
||||
if (CheckNext) {
|
||||
// We also check the event immediately following this one:
|
||||
e = Schedule->Events()->Next(e);
|
||||
if (e && !e->HasTimer() && Matches(e) != tmNone) {
|
||||
SpawnPatternTimer(e, Timers);
|
||||
TimersSpawned = true;
|
||||
}
|
||||
}
|
||||
if (CheckThis || CheckNext)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return TimersSpawned;
|
||||
}
|
||||
|
||||
bool cTimer::SetEventFromSchedule(const cSchedules *Schedules)
|
||||
{
|
||||
if (IsPatternTimer())
|
||||
return SetEvent(NULL);
|
||||
const cSchedule *Schedule = Schedules->GetSchedule(Channel());
|
||||
if (Schedule && Schedule->Events()->First()) {
|
||||
if (Schedule->Modified(scheduleState)) {
|
||||
@ -707,7 +906,7 @@ void cTimer::Skip(void)
|
||||
|
||||
void cTimer::OnOff(void)
|
||||
{
|
||||
if (IsSingleEvent())
|
||||
if (IsSingleEvent() || IsPatternTimer())
|
||||
InvFlags(tfActive);
|
||||
else if (day) {
|
||||
day = 0;
|
||||
@ -718,6 +917,8 @@ void cTimer::OnOff(void)
|
||||
else
|
||||
SetFlags(tfActive);
|
||||
SetEvent(NULL);
|
||||
if (HasFlags(tfActive))
|
||||
scheduleState = -1; // have pattern timers spawn if necessary
|
||||
Matches(); // refresh start and end time
|
||||
}
|
||||
|
||||
@ -831,7 +1032,7 @@ const cTimer *cTimers::GetNextActiveTimer(void) const
|
||||
{
|
||||
const cTimer *t0 = NULL;
|
||||
for (const cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
if (!ti->Remote()) {
|
||||
if (!ti->Remote() && !ti->IsPatternTimer()) {
|
||||
ti->Matches();
|
||||
if ((ti->HasFlags(tfActive)) && (!t0 || ti->StopTime() > time(NULL) && ti->Compare(*t0) < 0))
|
||||
t0 = ti;
|
||||
@ -882,8 +1083,22 @@ const cTimer *cTimers::UsesChannel(const cChannel *Channel) const
|
||||
bool cTimers::SetEvents(const cSchedules *Schedules)
|
||||
{
|
||||
bool TimersModified = false;
|
||||
for (cTimer *ti = First(); ti; ti = Next(ti))
|
||||
for (cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
if (!ti->IsPatternTimer())
|
||||
TimersModified |= ti->SetEventFromSchedule(Schedules);
|
||||
}
|
||||
return TimersModified;
|
||||
}
|
||||
|
||||
bool cTimers::SpawnPatternTimers(const cSchedules *Schedules)
|
||||
{
|
||||
bool TimersModified = false;
|
||||
for (cTimer *ti = First(); ti; ti = Next(ti)) {
|
||||
if (ti->IsPatternTimer() && ti->Local()) {
|
||||
if (ti->HasFlags(tfActive))
|
||||
TimersModified |= ti->SpawnPatternTimers(Schedules, this);
|
||||
}
|
||||
}
|
||||
return TimersModified;
|
||||
}
|
||||
|
||||
@ -896,6 +1111,7 @@ bool cTimers::DeleteExpired(void)
|
||||
while (ti) {
|
||||
cTimer *next = Next(ti);
|
||||
if (!ti->Remote() && ti->Expired()) {
|
||||
ti->SetEvent(NULL); // Del() doesn't call ~cTimer() right away, so this is necessary here
|
||||
isyslog("deleting timer %s", *ti->ToDescr());
|
||||
Del(ti);
|
||||
TimersModified = true;
|
||||
|
16
timers.h
16
timers.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: timers.h 4.12 2019/05/23 09:47:19 kls Exp $
|
||||
* $Id: timers.h 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TIMERS_H
|
||||
@ -20,10 +20,14 @@ enum eTimerFlags { tfNone = 0x0000,
|
||||
tfInstant = 0x0002,
|
||||
tfVps = 0x0004,
|
||||
tfRecording = 0x0008,
|
||||
tfSpawned = 0x0010,
|
||||
tfAvoid = 0x0020,
|
||||
tfAll = 0xFFFF,
|
||||
};
|
||||
enum eTimerMatch { tmNone, tmPartial, tmFull };
|
||||
|
||||
class cTimers;
|
||||
|
||||
class cTimer : public cListObject {
|
||||
friend class cMenuEditTimer;
|
||||
private:
|
||||
@ -40,13 +44,14 @@ private:
|
||||
int stop;
|
||||
int priority;
|
||||
int lifetime;
|
||||
mutable char pattern[NAME_MAX * 2 + 1]; // same size as 'file', to be able to initially fill 'pattern' with 'file' in the 'Edit timer' menu
|
||||
mutable char file[NAME_MAX * 2 + 1]; // *2 to be able to hold 'title' and 'episode', which can each be up to 255 characters long
|
||||
char *aux;
|
||||
char *remote;
|
||||
const cEvent *event;
|
||||
public:
|
||||
cTimer(bool Instant = false, bool Pause = false, const cChannel *Channel = NULL);
|
||||
cTimer(const cEvent *Event);
|
||||
cTimer(const cEvent *Event, const char *FileName = NULL, const cTimer *PatternTimer = NULL);
|
||||
cTimer(const cTimer &Timer);
|
||||
virtual ~cTimer();
|
||||
cTimer& operator= (const cTimer &Timer);
|
||||
@ -63,12 +68,14 @@ public:
|
||||
int Stop(void) const { return stop; }
|
||||
int Priority(void) const { return priority; }
|
||||
int Lifetime(void) const { return lifetime; }
|
||||
const char *Pattern(void) const { return pattern; }
|
||||
const char *File(void) const { return file; }
|
||||
time_t FirstDay(void) const { return weekdays ? day : 0; }
|
||||
const char *Aux(void) const { return aux; }
|
||||
const char *Remote(void) const { return remote; }
|
||||
bool Local(void) const { return !remote; } // convenience
|
||||
time_t Deferred(void) const { return deferred; }
|
||||
cString PatternAndFile(void) const;
|
||||
cString ToText(bool UseChannelID = false) const;
|
||||
cString ToDescr(void) const;
|
||||
const cEvent *Event(void) const { return event; }
|
||||
@ -80,13 +87,17 @@ public:
|
||||
bool DayMatches(time_t t) const;
|
||||
static time_t IncDay(time_t t, int Days);
|
||||
static time_t SetTime(time_t t, int SecondsFromMidnight);
|
||||
void SetPattern(const char *Pattern);
|
||||
void SetFile(const char *File);
|
||||
bool IsPatternTimer(void) const { return *pattern; }
|
||||
bool Matches(time_t t = 0, bool Directly = false, int Margin = 0) const;
|
||||
eTimerMatch Matches(const cEvent *Event, int *Overlap = NULL) const;
|
||||
bool Expired(void) const;
|
||||
time_t StartTime(void) const;
|
||||
time_t StopTime(void) const;
|
||||
void SetId(int Id);
|
||||
void SpawnPatternTimer(const cEvent *Event, cTimers *Timers);
|
||||
bool SpawnPatternTimers(const cSchedules *Schedules, cTimers *Timers);
|
||||
bool SetEventFromSchedule(const cSchedules *Schedules);
|
||||
bool SetEvent(const cEvent *Event);
|
||||
void SetRecording(bool Recording);
|
||||
@ -182,6 +193,7 @@ public:
|
||||
const cTimer *GetNextActiveTimer(void) const;
|
||||
const cTimer *UsesChannel(const cChannel *Channel) const;
|
||||
bool SetEvents(const cSchedules *Schedules);
|
||||
bool SpawnPatternTimers(const cSchedules *Schedules);
|
||||
bool DeleteExpired(void);
|
||||
void Add(cTimer *Timer, cTimer *After = NULL);
|
||||
void Ins(cTimer *Timer, cTimer *Before = NULL);
|
||||
|
8
tools.c
8
tools.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: tools.c 4.13 2020/11/22 13:32:05 kls Exp $
|
||||
* $Id: tools.c 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#include "tools.h"
|
||||
@ -198,6 +198,12 @@ int strcountchr(const char *s, char c)
|
||||
return n;
|
||||
}
|
||||
|
||||
const char *strgetlast(const char *s, char c)
|
||||
{
|
||||
const char *p = strrchr(s, c);
|
||||
return p ? p + 1 : s;
|
||||
}
|
||||
|
||||
char *stripspace(char *s)
|
||||
{
|
||||
if (s && *s) {
|
||||
|
30
tools.h
30
tools.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: tools.h 4.18 2020/09/16 13:48:33 kls Exp $
|
||||
* $Id: tools.h 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TOOLS_H
|
||||
@ -193,6 +193,33 @@ public:
|
||||
static cString vsprintf(const char *fmt, va_list &ap);
|
||||
};
|
||||
|
||||
class cNullTerminate {
|
||||
private:
|
||||
char *p;
|
||||
char c;
|
||||
public:
|
||||
cNullTerminate(void) {
|
||||
p = NULL;
|
||||
c = 0;
|
||||
}
|
||||
cNullTerminate(char *s) {
|
||||
Set(s);
|
||||
}
|
||||
~cNullTerminate() {
|
||||
if (p)
|
||||
*p = c;
|
||||
}
|
||||
void Set(char *s) {
|
||||
if (s) {
|
||||
p = s;
|
||||
c = *s;
|
||||
*s = 0;
|
||||
}
|
||||
else
|
||||
p = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
ssize_t safe_read(int filedes, void *buffer, size_t size);
|
||||
ssize_t safe_write(int filedes, const void *buffer, size_t size);
|
||||
void writechar(int filedes, char c);
|
||||
@ -206,6 +233,7 @@ char *strreplace(char *s, char c1, char c2);
|
||||
char *strreplace(char *s, const char *s1, const char *s2); ///< re-allocates 's' and deletes the original string if necessary!
|
||||
const char *strchrn(const char *s, char c, size_t n); ///< returns a pointer to the n'th occurrence (counting from 1) of c in s, or NULL if no such character was found. If n is 0, s is returned.
|
||||
int strcountchr(const char *s, char c); ///< returns the number of occurrences of 'c' in 's'.
|
||||
const char *strgetlast(const char *s, char c); // returns the part of 's' after the last occurrence of 'c', or 's' if there is no 'c'.
|
||||
inline char *skipspace(const char *s)
|
||||
{
|
||||
if ((uchar)*s > ' ') // most strings don't have any leading space, so handle this case as fast as possible
|
||||
|
7
vdr.1
7
vdr.1
@ -8,7 +8,7 @@
|
||||
.\" License as specified in the file COPYING that comes with the
|
||||
.\" vdr distribution.
|
||||
.\"
|
||||
.\" $Id: vdr.1 4.4 2018/04/10 13:58:06 kls Exp $
|
||||
.\" $Id: vdr.1 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
.\"
|
||||
.TH vdr 1 "15 Apr 2018" "2.4" "Video Disk Recorder"
|
||||
.SH NAME
|
||||
@ -305,6 +305,11 @@ The actual data files of a recording.
|
||||
Contains all current EPG data. Can be used for external processing and will
|
||||
also be read at program startup to have the full EPG data available immediately.
|
||||
.TP
|
||||
.I donerecs.data
|
||||
Contains the names of recordings that have been done by pattern timers with '@'
|
||||
as the first character of the pattern. File names are appended to this file after
|
||||
a recording has finished, and the entire file is read upon startup of VDR.
|
||||
.TP
|
||||
.I .update
|
||||
If this file is present in the video directory, its last modification time will
|
||||
be used to trigger an update of the list of recordings in the "Recordings" menu.
|
||||
|
43
vdr.5
43
vdr.5
@ -8,7 +8,7 @@
|
||||
.\" License as specified in the file COPYING that comes with the
|
||||
.\" vdr distribution.
|
||||
.\"
|
||||
.\" $Id: vdr.5 4.8 2018/04/10 13:58:16 kls Exp $
|
||||
.\" $Id: vdr.5 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
.\"
|
||||
.TH vdr 5 "15 Apr 2018" "2.4" "Video Disk Recorder Files"
|
||||
.SH NAME
|
||||
@ -317,10 +317,12 @@ The individual bits in this field have the following meaning:
|
||||
.TS
|
||||
tab (@);
|
||||
l l.
|
||||
\fB1\fR@the timer is active (and will record if it hits)
|
||||
\fB2\fR@this is an instant recording timer
|
||||
\fB4\fR@this timer uses VPS
|
||||
\fB8\fR@this timer is currently recording (may only be up-to-date with SVDRP)
|
||||
\fB0x0001\fR@the timer is active (and will record if it hits)
|
||||
\fB0x0002\fR@this is an instant recording timer
|
||||
\fB0x0004\fR@this timer uses VPS
|
||||
\fB0x0008\fR@this timer is currently recording (may only be up-to-date with SVDRP)
|
||||
\fB0x0010\fR@this timer was spawned from a pattern timer
|
||||
\fB0x0020\fR@this timer will store the recording's name in donerecs.data
|
||||
.TE
|
||||
|
||||
All other bits are reserved for future use.
|
||||
@ -425,6 +427,37 @@ by the title and episode information from the EPG data at the time of
|
||||
recording (if that data is available). If at the time of recording either
|
||||
of these cannot be determined, \fBTITLE\fR will default to the channel name, and
|
||||
\fBEPISODE\fR will default to a blank.
|
||||
|
||||
The file name can be prepended with a pattern, enclosed in curly braces, as in
|
||||
|
||||
{Columbo}Movies~TITLE
|
||||
|
||||
which makes this a "pattern timer". A pattern timer records every event on the
|
||||
given channel where the title contains the pattern (case sensitive).
|
||||
The following special characters can be used in a pattern:
|
||||
.TS
|
||||
tab (;);
|
||||
l l.
|
||||
\fB^\fR;anchor to the beginning of the event's title
|
||||
\fB$\fR;anchor to the end of the event's title
|
||||
\fB*\fR;match every event
|
||||
\fB@\fR;avoid duplicate recordings
|
||||
.TE
|
||||
|
||||
If \fB@\fR is used, it must be the very first character of the pattern.
|
||||
If both \fB@\fR and \fB^\fR are used, \fB@\fR must come first.
|
||||
If \fB*\fR is used, it must be the only character in the pattern and may only be
|
||||
prepended with \fB@\fR.
|
||||
|
||||
In addition to TITLE and EPISODE you can use the following macros to compose the file
|
||||
name (the curly braces are part of the macros):
|
||||
.TS
|
||||
tab (@);
|
||||
l l.
|
||||
{<}@everything before the matching pattern
|
||||
{>}@everything after the matching pattern
|
||||
{=}@the matching pattern itself (just for completeness)
|
||||
.TE
|
||||
.TP
|
||||
.B Auxiliary data
|
||||
An arbitrary string that can be used by external applications to store any
|
||||
|
10
vdr.c
10
vdr.c
@ -22,7 +22,7 @@
|
||||
*
|
||||
* The project's page is at http://www.tvdr.de
|
||||
*
|
||||
* $Id: vdr.c 4.34 2020/11/20 13:49:58 kls Exp $
|
||||
* $Id: vdr.c 5.1 2020/12/26 15:49:01 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -784,6 +784,7 @@ int main(int argc, char *argv[])
|
||||
KeyMacros.Load(AddDirectory(ConfigDirectory, "keymacros.conf"), true);
|
||||
Folders.Load(AddDirectory(ConfigDirectory, "folders.conf"));
|
||||
CamResponsesLoad(AddDirectory(ConfigDirectory, "camresponses.conf"), true);
|
||||
DoneRecordingsPattern.Load(AddDirectory(CacheDirectory, "donerecs.data"));
|
||||
|
||||
if (!*cFont::GetFontFileName(Setup.FontOsd)) {
|
||||
const char *msg = "no fonts available - OSD will not show any text!";
|
||||
@ -1098,15 +1099,20 @@ int main(int argc, char *argv[])
|
||||
static cStateKey TimersStateKey;
|
||||
cTimers *Timers = cTimers::GetTimersWrite(TimersStateKey);
|
||||
{
|
||||
LOCK_CHANNELS_READ; // Channels are needed for spawning pattern timers!
|
||||
// Assign events to timers:
|
||||
static cStateKey SchedulesStateKey;
|
||||
if (TimersStateKey.StateChanged())
|
||||
SchedulesStateKey.Reset(); // we assign events if either the Timers or the Schedules have changed
|
||||
bool TimersModified = false;
|
||||
if (const cSchedules *Schedules = cSchedules::GetSchedulesRead(SchedulesStateKey)) {
|
||||
Timers->SetSyncStateKey(StateKeySVDRPRemoteTimersPoll);
|
||||
Timers->SetSyncStateKey(StateKeySVDRPRemoteTimersPoll); // setting events shall not trigger a remote timer poll...
|
||||
if (Timers->SetEvents(Schedules))
|
||||
TimersModified = true;
|
||||
if (Timers->SpawnPatternTimers(Schedules)) {
|
||||
StateKeySVDRPRemoteTimersPoll.Reset(); // ...but spawning new timers must!
|
||||
TimersModified = true;
|
||||
}
|
||||
SchedulesStateKey.Remove();
|
||||
}
|
||||
TimersStateKey.Remove(TimersModified); // we need to remove the key here, so that syncing StateKeySVDRPRemoteTimersPoll takes effect!
|
||||
|
Loading…
Reference in New Issue
Block a user