=encoding utf8

=for syntax specification:
https://perldoc.perl.org/perlpod

=head1 NAME

F<EPGSearch> – search timers and replacement of the VDR's default schedules menu

=head1 OVERVIEW

Since the former F<README> got overly large, this man page serves as replacement
and explains some features and behaviors in detail. It's thus not really a manual, but an
extended F<README>.

=head1 CONTENT

=over 4

=item 1. Using variables in the directory entry of a search timer

=item 2. The format of the file F<epgsearch.conf>

=item 3. Description of the search process

=item 4. How do search timers work?

=item 5. How to trigger a search-timer update?

=item 6. The sources of the C<Select directory> menu

=item 7. Language-dependent commands for the EPG

=item 8. Usage from other plugins or scripts

=item 9. The SVDRP interface

=item 10. Customizing the EPG menus

=item 11. Working with the timer-conflict menu

=item 12. User-defined variables

=item 13. E-mail notifications

=item 14. The F<conf.d> directory

=back

=head1 1. Using variables in the directory entry of a search timer

When using extended EPG information, variables can be part of
the directory entry of a search timer. These variables always have
the syntax C<%Variable%>. The name of a variable corresponds with the
internal name of an extended EPG information as specified in the file
F<epgsearchcats.conf>; samples can be found in subdirectory F<conf>
of the plugin's source directory.

Example:

=over 4

    1|Category|Kind|Information,Children,Music,Series,Show,Movie,Sports|3

=back

The category with ID C<1> has the internal name C<Category>. So you could
refer to it with C<%Category%>. Variable names are case-insensitive.

Sample directory entries could look like this:

=over 4

    My Movies~%Category%
    Children's Movies~%category%
    %CATEGORY%~%genre%

=back

Three more variables are available:

=over 4

=item B<%Title%>

Substituted by the name of the event.

=item B<%Subtitle%>

Substituted by the short text of the event.

=item B<%ChLng%>

Substituted by the long name of the channel on which the event is broadcasted.

=back

If neither C<%Title%> nor C<%Subtitle%> is included or part of an inserted user-defined
variable, the title is always automatically appended to the directory entry once a timer
is created. If C<Series recording> is set to C<yes> in the search timer, the subtitle
will be automatically appended, too. So, the directory entry:

=over 4

    %Category%~%Genre%~%Title%~%Subtitle%

=back

is the same as:

=over 4

    %Category%~%Genre%

=back

if C<Series recording> set to C<yes>.

B<Attention:> Title and subtitle will not be appended automatically if one of
the variables C<%Title%> or C<%Subtitle%> is part of the directory specification.
This allows forming directory entries like this one:

=over 4

    %Category%~%Genre%~%Title%~%Episode%~%Subtitle%

=back

Furthermore, the following search variables are available in addition:

=over 4

=item B<%Search.Query%>

Substituted by the search term of the search timer.

=item B<%Search.Series%>

Substituted by C<1> if the search has the C<Series recording> flag set, or C<0> otherwise.

=back

See also B<epgsearchuservars.conf>(5).

=head1 2. The format of the file F<epgsearch.conf>

Every line within the file represents a search or search timer,
comprising the following fields:

=over 4

=item B<1 – Unique identifier (ID)>

Integer with a positive value.

=item B<2 – Search term ("query")>

String specifying the search criterion.

=item B<3 – Use time>

Flag with values 0 = no, 1 = yes.

=item B<4 – Start after [HHMM]>

Integer with HH = 0..23, MM = 0..59; other values may result in undefined behavior.

=item B<5 – Start before [HHMM]>

Integer with HH = 0..23, MM = 0..59; other values may result in undefined behavior.

=item B<6 – Use channel>

Enumeration with values 0 = no, 1 = interval, 2 = channel group, 3 = FTA (free-to-air) only.

=item B<7 – Channel selection>

=over 4

=item if 'use channel' = 1:

String with C<ChannelID> or C<MinChannelID>|C<MaxChannelID>; the channel
identifiers must conform to the VDR notation (e.g., C<S19.2E-1-1019-10301>).

B<Attention:> Please check the range settings of your search timers
after changing the sequence of the channels!

=item if 'use channel' = 2:

String referring to a previously configured channel-group name.

=back

=item B<8 – Match case>

Flag with values 0 = no, 1 = yes.

=item B<9 – Search mode>

Enumeration with the following values:

=over 4

=item 0 = phrase

=item 1 = all words

=item 2 = at least one word

=item 3 = match exactly

=item 4 = regular expression

=item 5 = fuzzy search (tolerance in field 42; not available for extended
EPG categories)

=back

See "Description of the search process" for how these modes
control the search.

=item B<10 – Use title>

Flag with values 0 = no, 1 = yes.

=item B<11 – Use subtitle>

Flag with values 0 = no, 1 = yes.

=item B<12 – Use description>

Flag with values 0 = no, 1 = yes.

=item B<13 – Use duration>

Flag with values 0 = no, 1 = yes.

=item B<14 – Minimum duration [HHMM]>

Integer with HH = 0..23, MM = 0..59; other values may result in undefined behavior.

=item B<15 – Maximum duration [HHMM]>

Integer with HH = 0..23, MM = 0..59; other values may result in undefined behavior.

=item B<16 – Use as search timer>

Enumeration with the following values:

=over 4

=item 0 = no

=item 1 = yes

=item 2 = time span (fields 48 and 49)

=back

Z<>

=item B<17 – Use day of week>

Flag with values 0 = no, 1 = yes.

=item B<18 – Day of week>

Integer value from −127 to 6. The encoding is twofold:

=over 4

=item if I<dow> ≥ 0: individual weekday

Enumeration with values 0 = Sunday, 1 = Monday, ..., 6 = Saturday.

=item if I<dow> < 0: set of weekdays

Integer in which the bits of −I<dow> represent the weekdays. Bit
masks result from shifting 0x01 by a weekday's enumeration value:

Z<>

=over 4

=item 0x01 = Sunday

=item 0x02 = Monday

=item 0x04 = Tuesday

=item 0x08 = Wednesday

=item 0x10 = Thursday

=item 0x20 = Friday

=item 0x40 = Saturday

=back

To encode the desired set of weekdays, the value resulting from
their ORed bit masks must be negated.

Example: −67 (negated: 0b01000011 = 0x40 | 0x02 | 0x01) encodes Saturday, Monday, and Sunday

=back

=item B<19 – Series recording>

Flag with values 0 = no, 1 = yes.

=item B<20 – Directory for recording>

String with the name of a directory beneath the VDR's video directory,
but without the path to that video directory.

=item B<21 – Priority of recording>

Integer value from 0 to 99.

=item B<22 – Lifetime of recording [days]>

Integer value from 0 to 99.

=item B<23 – Margin at start [minutes]>

=for consideration:
Should we limit the margins to some reasonable value, like 2 hours = 0..120?

Integer with a positive value.

=item B<24 – Margin at stop [minutes]>

Integer with a positive value.

=item B<25 – Use VPS>

Flag with values 0 = no, 1 = yes.

=item B<26 – Action>

Enumeration with the following values:

=over 4

=item 0 = record

=item 1 = announce by OSD (no timer)

=item 2 = switch only (no timer)

=item 3 = announce by OSD and switch (no timer)

=item 4 = announce by e-mail

=item 5 = inactive record

=back

Z<>

=item B<27 – Use extended EPG information>

Flag with values 0 = no, 1 = yes.

=item B<28 – Extended EPG information values>

List of extended EPG category data, each represented by a tuple of:

=over 4

=item 28.1 – Identifier

Unique identifier of the extended EPG category as specified
in F<epgsearchcats.conf>.

=item 28.2 – Category values

Comma-separated list of values as specified for the EPG category in
F<epgsearchcats.conf>. Spaces around values are ignored.
A C<:> character, like in C<16:9>, must be encoded as C<!^colon^!>.

=back

The C<|> character separates adjacent category tuples,
whereas C<#> separates ID and category names.

Example: C<1#Movie, Series|2#Horror|8#16!^colon^!9>

=item B<29 – Avoid repeats>

Flag with values 0 = no, 1 = yes.

=item B<30 – Allowed repeats>

Integer value from 0 to 99.

=item B<31 – Compare title (when testing for repeats)>

Flag with values 0 = no, 1 = yes.

=item B<32 – Compare subtitle (when testing for repeats)>

Enumeration with value 0 = no, 1 = yes, 2 = allow empty.

=item B<33 – Compare summary (when testing for repeats)>

Flag with values 0 = no, 1 = yes.

=item B<34 – Compare categories (when testing for repeats)>

Integer in which each bit represents an extended EPG category.
The first EPG category specified in F<epgsearchcats.conf> is
represented by bit 0 (0x01), the second by bit 1 (0x02), etc.
A nonzero value enables comparison.

B<Note:> The values of the EPG category identifiers (field 1 of an
EPG category entry) are of no relevance for encoding the bit field.
Changes to EPG categories may require an update of search timers.

=item B<35 – Only repeats within ... days>

Integer value from 0 to 999.

=item B<36 – Delete recordings after ... days>

Integer value from 0 to 999.

=item B<37 – Keep ... recordings>

Integer value from 0 to 999.

=item B<38 – Switch ... minutes before start>

Integer value from 0 to 99; only considered if 'action' = 2.

=item B<39 – Pause when ...recordings exist>

Integer value from 0 to 999.

=item B<40 – Blacklist usage mode>

Enumeration with values 0 = only global, 1 = selection, 2 = all, 3 = none.

=item B<41 – Blacklist selection>

List of blacklist identifiers, separated by C<|> characters;
only considered if 'blacklist usage mode' = 1.

=item B<42 – Fuzzy tolerance>

Integer value from 1 to 9, serving as threshold for fuzzy searching;
only considered if 'search mode' = 5.

=item B<43 – Use in favorites menu>

Flag with values 0 = no, 1 = yes.

=item B<44 – Result menu layout for favorites menu>

Integer referencing a search-result template specified in F<epgsearchmenu.conf>.
The value is the index (starting at 0) within all entries having a prefix of
C<MenuSearchResults>; see "10. Customizing the EPG menus" in B<epgsearch>(4)
for details.

B<Note:> The field is only of relevance if multiple search-result templates
have been specified.

=item B<45 – Auto delete mode>

Enumeration with the following values:

=over 4

=item 0 = don't delete the search timer

=item 1 = delete after a number of recordings (field 46)

=item 2 = delete after a number of days after the first recording (field 47)

=back

Z<>

=item B<46 – Delete after ... recordings>

Integer value from 0 to 999; only considered if 'auto delete mode' = 1.

=item B<47 – Delete after ... days after first recording>

Integer value from 0 to 999; only considered if 'auto delete mode' = 2.

=item B<48 – First day (use as search timer from)>

Date and time in I<Epoch> encoding (i.e., seconds since 1970-01-01 00:00 UTC)
from which on the search timer is active; a value of 0 disables the check.

B<Note:> Any I<Epoch> value can be supplied. Thus, providing a time within
a day (instead of midnight) will keep the timer inactive until that intra-day
time has been reached.

=item B<49 – Last day (use as search timer until)>

Date and time in I<Epoch> encoding (i.e., seconds since 1970-01-01 00:00 UTC)
until which the search timer is active; a value of 0 disables the check.

B<Note:> Any I<Epoch> value can be supplied. Thus, providing a time within
a day (instead of midnight) will keep the timer active until that intra-day
time has been reached.

=item B<50 – Matching mode of extended EPG information>

Enumeration with the following values:

=over 4

=item 0 = all selected categories

=item 1 = all except missing categories

=item 2 = at least one category

=back

This allows including events with missing or just some matching categories.
But without other sufficiently limiting criteria, this could yield a huge
number of results.

=item B<51 – Unmute sound>

Flag with values 0 = no, 1 = yes; only considered if 'action' = 2 or 3.

=item B<52 – Minimum match in percent>

Integer value from 1 to 100, specifying the minimum match required
to avoid repeats when summaries are to be compared; only considered
if 'compare summary' = 1.

=item B<53 – Content descriptors>

String with content descriptors to be checked. Content descriptors are
values from 0 to 255 (see DIN EN 300 468, Table 18), encoded as 2-digit
hexadecimal numbers. The upper nibble (bits [7..4]) constitutes a content
group, and the lower nibble (bits [3..0]) represents a distinct descriptor
within that group. A group's first descriptor with a value of 0 usually is
a general classification of that group (like 0x10 = movie, drama), whereas
values 1..15 provide a subordinate, finer classification (like 0x11 = detective,
thriller; 0x14 = comedy). But since content group 11 (special characteristics)
does not comply to this scheme (as can be seen from 0xB0 = original language;
0xB1 = black & white), a distinct matching mode for its descriptors is available.

The content descriptors to be checked are the concatenation of their 2-digit
hexadecimal values without separators.

B<Example:> Content identifiers 17 (detective, thriller), 20 (comedy) and
176 (original language) are encoded as C<1114B0>.

The settings of fields 55 (content categories) and 56 (special characteristics)
determine the conditions for an event to match the selected content descriptors.

Leave empty for not taking content descriptors into account.

=item B<54 – Compare date (when testing for repeats)>

Enumeration with the values 0 = no, 1 = same day, 2 = same week, 3 = same month.

=item B<55 – Matching mode of content categories>

Enumeration with the following values:

=over 4

=item 0 = all selected descriptors

=item 1 = any selected descriptor

=item 2 = some selected descriptor per group

=back

Modes 0 and 1 instantly match across all category groups but nevertheless use the
matching mode of field 56 for checking the special characteristics. Thus, combinations
like 'AND' for the category groups and 'OR' within the special characteristics can occur,
and vice versa.

Mode 2, however, uses a two-stage evaluation: First, category groups with selected
content descriptors are checked (groups without selected content descriptors are
not considered). A category group matches if an event includes at least one of the
group's selected descriptors ('some selected', OR), except for the special-characteristics
group that again uses the matching mode of field 56. Second, all checked groups must have
matched ('per group', AND).

Only considered if 'content descriptors' is not empty.

=item B<56 – Matching mode of special characteristics>

Enumeration with values 0 = all selected descriptors, 1 = any selected descriptor;
only considered if 'content descriptors' is not empty.

=item B<57 – Use parental rating>

Flag with values 0 = no, 1 = yes.

=item B<58 – Minimum parental rating>

Integer value from 0 to 18.

=item B<59 – Maximum parental rating>

Integer value from 0 to 18.

=back

A search timer's entry is considered valid if covers at least the first 11 fields.

The fields ("parameters") of a search timer are separated by C<:> characters. Thus,
a C<:> character in strings, like the search term or the directory, will be encoded
as C<|> character. If a C<|> character should be part of the string as well, like in
regular expressions, it will be encoded as C<!^pipe^!> (which is rather ugly but
required for backward compatibility).

Fields depending on another field and being void due to that field's setting can
(and actually should) be left empty. For instance, a search timer not having a time
constraint can leave the fields 'start after' and 'start before' empty:

=over 4

    1:My favorite series: 0::: 0::0:0
                          ^^^^

=back

Furthermore, leading and trailing whitespace around a field value is discarded.
This implies, however, that strings cannot start or end with whitespace.

B<Note:> Strings within fields must not be enclosed in quotations marks or apostrophes,
even if this should be indicated in a field's description. These characters have just
been inserted during compilation of this man page.

See also B<epgsearch.conf>(5).

=head1 3. Description of the search process

First, a temporary search text is created for each broadcast, in which
title, subtitle and description are separated by C<~> characters:

=over 4

    title~subtitle~description

=back

Depending on the settings of C<use title>, C<use subtitle> and C<use description>,
these components are either inserted or remain empty.

If C<match case> has not been set, the search text and the search term are
transformed into lowercase.

Depending on the search mode, the search term will then be looked up in
the search text:

=over 4

=item B<Phrase>

Matches if the search term is found anywhere in the search text.

=item B<All words>

=item B<At least one word>

First, the search term will be split into single words; delimiters are
spaces and one of the C<,;|~> characters.
Second, the search succeeds if at least one word, or all words, appear
in the search text.

=item B<Match exactly>

Matches if search term and search text are identical.

=item B<Regular expression>

The search is performed with a regular expression. Two standards are
supported: extended POSIX and Perl compatible regular expressions (PCRE)
(see F<INSTALL>).

B<Note>: Unlike in Perl, leading and trailing C</> characters are not
required for the search term.

=item B<Fuzzy>

Compares the search term based upon the Levenshtein-Distance algorithm.
The value of the field C<fuzzy tolerance> determines how much deviation
is acceptable.

B<Note:> The search term is limited to 32 characters when using the fuzzy
mode.

=back

If the search was successful so far, the other criteria (start time,
duration, weekday, etc.) are checked.

=head1 4. How do search timers work?

With each update, the plugin first sorts the search timers by timer
priority (descending) and search term, before it searches for new matches
of search timers. If a new match is found, a new timer will be created.

For series recordings, the subtitle is appended to the recording
directory. Many providers deliver the subtitle just a few days before
the event. If unavailable, the plugin temporarily uses date and time for
the subtitle but replaces them once the subtitle has become available.

Start and stop times of broadcasts often vary slightly. To avoid
many different timers for the same event, the plugin checks whether
another timer's start and stop times only differ by a maximum of 10 minutes;
if an event's duration is less than 10 minutes, the durations will be compared
instead.

If a match is found, a present timer will be modified, else a new timer
will be created; inactive timers will not be updated. Furthermore, manually
adapted priority or lifetime settings will not be changed upon updates.

If C<action> was set to a variant of 'announce (no timer)', no timer
will be created. Instead, a notification about the event will be issued:
An OSD message will be displayed upon each scan, but only if there was
no previous timer for the event. An e-mail will be sent according to
the schedule configured if timers have been created or changed.

=head1 5. How to trigger a search-timer update?

The update of search timers runs in a thread of its own. An update
can be triggered in several ways:

=over 4

=item B<Periodically>

The search timers will be updated a few seconds after the VDR has started.
Once finished, the setup option C<Update interval [min]> determines in which
intervals future updates shall be done.

=item B<Externally>

The thread observes the file C<.epgsearchupdate> in the
plugin's configuration directory. After executing:

=over 4

    touch /path_to_file/.epgsearchupdate

=back

an update will be performed. This offers a simple way to
trigger an update, for example when running a script.

=item B<Internally>

Calling C<Actions> » C<Trigger search timer update> or pressing C<3>
in the menu C<Search entries> will also trigger an update.

=item B<By other plugins>

The service C<Epgsearch-updatesearchtimers-v1.0> can be used with
the VDR's service interface by other plugins. The caller can request
an OSD notification when the update has been finished.

=back

=head1 6. The sources of the C<Select directory> menu

This menu displays directories that can be used for both search timers
and ordinary timers. The items displayed are collected from the following
sources:

=over 2

=item * current recording directories

=item * current timer directories

=item * directories used in search timers

=item * directories specified in F<epgsearchdirs.conf>, see B<epgsearchdirs.conf>(5)

=item * entries in the VDR's F<folders.conf>

=back

The menu merges these directories and displays only distinct
directories. The key C<yellow> allows changing the level of the
directories shown. Should there be items containing EPG category
variables like C<%Genre%>, these entries are always shown before other
directories. They also do not depend on the level, but are always shown
with their full directory path.

If this menu is called from the timer-edit menu and the selected item
already contains the variables C<%Title%> or C<%Subtitle>, the timer's
C<File> entry gets cleared, since title or subtitle already included
in the C<Directory> item.

This list can also be accessed via the SVDRP command C<LSRD>.

=head1 7. Language-dependent commands for the EPG

If you like to have a language-dependent list of commands, simply
translate your present F<epgsearchcmds.conf> to your preferred OSD
language and store it with the filename F<epgsearchcmds-E<lt>LOCE<gt>.conf>,
where F<E<lt>LOCE<gt>> is the locale's code from F<i18n.c>:


=over 4

    { "eng,dos",
      "deu,ger",
      "slv",
      "ita",
      "dut,nla,nld",
      "por",
      "fra,fre",
      "nor",
      "fin,smi",
      "pol",
      "esl,spa",
      "ell,gre",
      "sve,swe",
      "rom,rum",
      "hun",
      "cat,cln",
      "rus",
      "hrv",
      "est",
      "dan"
      // see the source file
      // for the complete list
    }

=back

If more codes are listed for a language, like C<eng,dos>, choose
one of them.

If a file corresponding to the VDR's OSD language is available, it
will be loaded. If no such file exists, the system will attempt to
load the F<epgsearchcmds.conf> file instead.

See also B<epgsearchcmds.conf>(5).

=head1 8. Usage from other plugins or scripts

Searching the EPG and other functionality can be used by other plugins
or scripts. There are two approaches:

=head2 8.1. File-based (intended for use in scripts)

Therefore simply create the file F<.epgsearchrc> in the plugin's
configuration directory with the following lines in it:

=over 4

    Search=the search term
    SearchMode=x  // 0 = phrase, 1 = all (default), 2 = single, 3 = exactly, 4 = regex
    ChannelNr=x   // searches on a specific channel, if present
    UseTitle=x    // 1 (default) or 0
    UseSubtitle=x // 1 (default) or 0
    UseDescr=x    // 1 (default) or 0

=back

At startup, EPGSearch will look for this file and, if found, return the
search results for the specified search. Once the search has finished,
the file will be removed.

Later on, another search can be triggered by means of the SVDRP interface.
Supposing that the key C<green> has been assigned to EPGSearch (see
B<epgsearch>(1), chapter 5), just call EPGSearch via F<svdrpsend>:

=over 4

    svdrpsend HITK green

=back

A sample script F<recrep.sh> that searches for the repeats of a recording
is provided in the subdirectory F<scripts> of EPGSearch.

=head2 8.2 Via plugin interface (intended for use in plugins)

A plugin can directly call two functions of EPGSearch with only some
lines of code:

=over 2

=item * searching the EPG for some criteria and displaying the list of results

=item * invoking the extended timer-edit menu

=back

A quick-and-dirty sample plugin provided in the EPGSearch F<source> directory
(F<vdr-epgsearchclient-0.0.1.tgz>) demonstrates the usage.

=head1 9. The SVDRP interface

EPGSearch implements an SVDRP interface that can be accessed like this:

=over 4

    svdrpsend PLUG epgsearch LSTS

=back

The following sections describe the commands available at the SVDRP interface.

=head2 9.1 Search management

=over 4

=item B<LSTS> [I<ID>]

Lists all searches, or just the one with the supplied I<ID>. The
format of the returned data is the same as in F<epgsearch.conf>
(see above).

=item B<NEWS> I<settings>

Adds a new search. The data format of I<settings> is identical to
the one used in F<epgsearch.conf> (see above).

The unique identifier (field 1) will be ignored. EPGSearch will
always assign the next free identifier and reports it in the
response:

=over 4

    svdrpsend PLUG epgsearch NEWS "0:Sample search:::::::::"

    220 HostName SVDRP VideoDiskRecorder 2.7.7; ...
    900 search 'Sample search' (with new ID 6) added
    221 HostName closing connection

=back

=item B<EDIS> I<parameters>

Modifies an existing search. The data format of I<parameters> is identical to
the one used in F<epgsearch.conf> (see above). The identifier in field 1
specifies the search to be modified.

B<Note:> An empty field (C<::>) is ignored. However, the values of the fields
C<search>, C<directory> and C<content descriptors> will be cleared if no values
have been supplied.

=item B<MODS> I<ID> ON|OFF

Turns the option C<Use as search timer> on or off.

=item B<DELS> I<ID>

Deletes the search with the supplied I<ID>.

=item B<SETS> ON|OFF

Starts (switches C<ON>) or stops (switches C<OFF>) the search-timer
background thread.

=item B<UPDS> [OSD]

Updates searches and search timers. Passing the optional keyword
C<OSD> displays an OSD message once the update has finished.

=item B<UPDT>

Reloads the file F<epgsearch.conf>, for instance, after an
external tool has modified it.

=item B<UPDD>

Reloads the file F<epgsearchdone.data>, for instance, after an
external tool has modified it.

=item B<FIND> <parameters>

Searches the EPG for matching events. The data format of I<parameters> is
identical to the one used in F<epgsearch.conf> (see above).

Returns one line per found event, formatted as the VDR's C<NEWT> command.
This comprises the following fields:

=over 4

    timer    : // 1 = create new timer
    channel  : // channel number in VDR's channel list
    date     : // date on which the event starts [YYYY-MM-DD]
    begin    : // start time of the event [HHMM]
    end      : // stop  time of the event [HHMM]
    priority : // priority for recording
    lifetime : // lifetime for recording
    file     : // timer file

=back

Example:

=over 4

    svdrpsend PLUG epgsearch FIND "0:The Rookie:::::::::"

    220 HostName SVDRP VideoDiskRecorder 2.7.7; ...
    900-NEWT 1:39:2025-08-07:1753:1845:50:99:The Rookie:
    221 HostName closing connection

=back

A search result can thus instantly be used to create a timer
for the corresponding event.

B<Note:> If not controlled by VPS, the date and start/stop times
include the start/stop margins specified in the parameters.

=item B<QRYS> I<ID>[|I<ID>|...]

Retrieves the results for a search with the supplied I<ID>. Multiple IDs,
separated by C<|> characters, can be supplied as well.

Returns one line per ID, using the following format:

=over 4

    search   : // unique identifier of the corresponding search
    event    : // unique identifier of the event within the VDR's schedules
    title    : // event title, with C<:> characters converted to C<|>
    subtitle : // event subtitle, with C<:> characters converted to C<|>
    begin    : // event start in Epoch encoding (i.e., seconds since 1970-01-01 00:00 UTC)
    end      : // event stop  as Epoch encoding (i.e., seconds since 1970-01-01 00:00 UTC)
    channel  : // channel ID in VDR's internal representation (e.g., S19.2E-1-1101-28106)
    start    : // timer start in Epoch encoding; only valid if 'timer' > 0
    stop     : // timer stop  in Epoch encoding; only valid if 'timer' > 0
    file	 : // timer file; only valid if 'timer' > 0
    timer    : // 0 = no timer, 1 = active timer, ... (VDR timer flags)

=back

Example:

=over 4

    svdrpsend PLUG epgsearch QRYS 0

    220 HostName SVDRP VideoDiskRecorder 2.7.7; ...
    900-0:3124:The Rookie:Heartbreak:1756901400:1756903800:S19.2E-1-1011-11130:1756901280:1756904400:The Rookie~Heartbreak:1
    221 HostName closing connection

=back

=item B<QRYS> I<parameters>

Retrieves the results for a search with the given I<parameters>, ignoring
the unique identifier in field 1.

=item B<QRYF> [I<hours>]

Retrieves the results for the favorites menu; see C<QRYS> for the data
format of the results. The optional parameter specifies the number of
hours to be inspected and defaults to 24 hours.

=item B<MENU> [NOW|PRG|SUM]

Invokes an EPGSearch menu or the summary of the current event:

=over 2

=item * NOW – ongoing broadcasts

=item * PRG – schedule of the current channel

=item * SUM – description of the current event

=back

B<Caution:> The menu will only be displayed if no other menu is open at
that time, else the currently shown menu will be closed. Thus, this
command is not fully deterministic.

=back

=head2 9.2 Channel-group management

=over 4

=item B<LSTC> [I<name>]

Lists all channel groups, or just the one with the supplied
I<name>. The format of the returned data is the
same as in F<epgsearchchangrps.conf>.

=item B<NEWC> I<settings>

Creates a new channel group. The data format of I<settings> is
the same as in F<epgsearchchangrps.conf>.

=item B<EDIC> I<settings>

Modifies an existing channel group. The data format of I<settings> is
the same as in F<epgsearchchangrps.conf>.

=item B<RENC> I<old-name>|I<new-name>

Renames an existing channel group.

=item B<DELC> I<name>

Deletes an existing channel group.

=back

=head2 9.3 Blacklist management

=over 4

=item B<LSTB> [I<ID>]

Retrieves all blacklists, or just the one with the supplied I<ID>. The format
of the returned data is the same as in F<epgsearchblacklists.conf>.

=item B<NEWB> I<settings>

Adds a new blacklist. The data format of I<settings> is the same as in
F<epgsearchblacklists.conf>.

The unique identifier (field 1) will be ignored. EPGSearch will always
assign the next free identifier and reports it in the response:

=over 4

    svdrpsend PLUG epgsearch NEWB "0:Sample blacklist:::::::::::::::::"

    220 HostName SVDRP VideoDiskRecorder 2.7.7; ...
    900 blacklist 'Sample blacklist' (with new ID 3) added
    221 HostName closing connection

=back

=item B<DELB> I<ID>

Deletes the blacklist with the supplied I<ID>.

=item B<EDIB> I<settings>

Modifies an existing blacklist. The data format of I<settings> is the same as in
F<epgsearchblacklists.conf>. The identifier in field 1 specifies the blacklist
to be modified.

B<Note:> An empty field (C<::>) is ignored. However, the values of the fields
C<search> and C<content descriptors> will be cleared if no values have been supplied.

=back

=head2 9.4 Search-template management

=over 4

=item B<LSTT> [I<ID>]

Lists all search templates, or just the one with the passed I<ID>. The format of
the returned data is the same as in F<epgsearch.conf> (see above).

=item B<NEWT> I<settings>

Adds a new search template. The data format of I<settings> is the same as in
F<epgsearch.conf> (see above).

The value of the search identifier (field 1) will be ignored.
EPGSearch will always assign the next free identifier and
reports it in the response:

=over 4

    svdrpsend PLUG epgsearch NEWT "0:Sample template:::::::::"

    220 HostName SVDRP VideoDiskRecorder 2.7.7; ...
    900 search template 'Sample template' (with new ID 4) added
    221 HostName closing connection

=back

=item B<EDIT> I<settings>

Modifies an existing search template The data format of I<settings> is the
same as in F<epgsearch.conf> (see above). The identifier in field 1 specifies the search
template to be modified.

B<Note:> An empty field (C<::>) is ignored. However, the values of the fields
C<search>, C<directory> and C<content descriptors> will be cleared if no
values have been supplied.

=item B<DELT> I<ID>

Deletes the search template with the supplied I<ID>.

=item B<DEFT> [I<ID>]

Returns the ID of the default search template. When supplying an
I<ID>, the corresponding search template will be set as new default.

=back

=head2 9.5 Extended EPG categories

=over 4

=item B<LSTE> [I<ID>]

Lists the extended EPG categories defined in F<epgsearchcats.conf>,
or just the one with the supplied I<ID>. The format of the returned
data is the same as in F<epgsearchcats.conf>.

=back

=head2 9.6 Timer conflicts

=over 4

=item B<LSCC> [REL]

Returns the current timer conflicts. With the option C<REL>, only
relevant conflicts are listed. The list of results looks like the
following example of two timer conflicts at a given time:

=over 4

    1190232780:152|30|50#152#45:45|10|50#152#45

=back

C<1190232780> is the time of the conflict in I<Epoch> encoding (i.e.,
seconds since 1970-01-01 00:00 UTC). It's followed by a list of timers
that have a conflict at this time.

C<152|30|50#152#45> is the description of the first conflicting timer:

=over 2

=item * C<152> is VDR's ID of this timer as returned by the VDR's C<LSTT> command

=item * C<30> is the percentage of recording that would be done (0..100)

=item * C<50#152#45> is the list of all timers involved in this conflict

=back

C<45|10|50#152#45> describes the another conflict for this point of time.

=back

=head2 9.7 Miscellaneous

=over 4

=item B<LSRD>

Lists all recording directories used in recordings, timers, search timers
or that are defined in F<epgsearchdirs.conf>.

=item B<SETP> [I<option>]

Returns the current value of the supplied setup option, or a
list of selected setup options with their current values.

The following setup options can be accessed:

=over 2

=item * I<ShowFavoritesMenu>

=item * I<UseSearchTimers>

=item * I<DefRecordingDir>

=item * I<AddSubtitleToTimerMode>

=item * I<DefPriority>

=item * I<DefLifetime>

=item * I<DefMarginStart>

=item * I<DefMarginStop>

=back

=back

=head1 10. Customizing the EPG menus

The file F<epgsearchmenu.conf> in the EPGSearch configuration
directory stores the settings for customizing the EPG menus.
Each line configures the display of a certain menu. The entries
specify the layouts for the following menus:

=over 4

=item B<MenuWhatsOnNow>

Template for the menu C<Now>.

=item B<MenuWhatsOnNext>

Template for the menu C<Next>.

=item B<MenuWhatsOnElse>

Template for the menu of a user-defined time.

=item B<MenuSchedule>

Template for the menu C<Schedule>.

=item B<MenuSearchResults>

Template for the menu C<Search results>.

=item B<MenuFavorites>

Template for the menu C<Favorites>.

=back

For example:

=over 4

    MenuWhatsOnNow=%chnr%:3|%progrt2s%:5| %time% %t_status%:8|%category%:6| %title% ~ %subtitle%:35
    MenuWhatsOnNext=%chnr%:3|%time% %t_status%:8|%category%:8| %title% ~ %subtitle%:35
    MenuWhatsOnElse=%chnr%:3|%time% %t_status%:8|%category%:8| %title% ~ %subtitle%:35
    MenuSchedule=%time% %t_status%:8|%genre%:14| %title% ~ %subtitle%:35
    MenuSearchResults=%chnr%:3|%datesh% %time% %t_status%:14|%genre%:8| %title%%colon% %subtitle%:35
    MenuFavorites=%chnr%:3|%time%:6|%timespan%:7|%t_status%:14|%genre%:8| %title%%colon%%subtitle%:35

=back

The entry C<MenuWhatsOnNow> instructs EPGSearch how to format a line for the menu
C<Now>: The menu's line will start with the channel number, followed by a progress
bar in F<text2skin> style, a single space, the start time, the timer status, the
value of the EPG category named C<Category> (e.g., "Movie") and, finally, the title
and subtitle.

The values for
C<MenuWhatsOnNext>, C<MenuWhatsOnElse>, C<MenuSchedule>, C<MenuSearchResults> and C<MenuFavorites>
specify the menu settings for
C<Next>, the menu of a user-defined time, C<Schedule>, C<Search results>, and C<Favorites>,
respectively. Without a corresponding entry, EPGSearch uses a menu's default layout.

The entry C<MenuSearchResults> has a special feature: If different layouts for search results
are desired depending on the search, more than one menu template can be provided.
For example, suppose the following entry gets added:

=over 4

    MenuSearchResultsTip of the Day=%chnr%:3|%time_w%:4|%t_status%:3|%genre%:10|%title%%colon% %subtitle%:35

=back

This will result in an additional menu item C<Result menu layout> in the menu
C<Edit search> that allows choosing between the menu's default template and own
templates. For the example above, C<Tip of the Day> will be listed as additional
option, since EPGSearch simply strips the prefix C<MenuSearchResults>. When displaying
the search results, the chosen layout will be used instead of the default one.

The following variables exist (case ignored):

=for time variables

=over 4

=item B<%Time%>

An event's start time in 'HH:MM' format.

=item B<%TimeEnd%>

An event's end time in 'HH:MM' format.

=item B<%Time_D%>

An event's start date in 'DD' format.

=item B<%Time_W%>

Name of the weekday on which an event starts.

=item B<%Time_Lng%>

An event's start date and time in I<Epoch> encoding
(i.e., seconds since 1970-01-01 00:00 UTC).

=item B<%TimeSpan%>

Time span til the start of an event (like C<in 15m>)
or the time an event is already running (like C<10m>).

=for date variables

=item B<%Date%>

An event's start date in 'DD.MM.YY' format.

=item B<%DateSh%>

An event's start date in 'DD.MM' format.

=item B<%Date_ISO%>

An event's start date in 'YYYY-MM-DD' format.

=item B<%Day%>

An event's start day (1..31).

=item B<%Week%>

Calendar week of an event's start date (01..53).

According to the ISO 8601 standard, Monday is the first day of a week.
Calendar week 1 is the first week where four or more days fall within
the new year, that is, the first week that contains a Thursday or has
January 4 in it.

=item B<%Month%>

An event's start month (1..12).

=item B<%Year%>

An event's start year (1970..2038, or even later).

=for event-specific variables

=item B<%EventID%>

An event's numeric identifier.

=item B<%LiveEventID%>

An event's identifier as used in the front end F<live>.

=item B<%Title%>

An event's title.

=item B<%Subtitle%>

An event's subtitle.

=item B<%Summary%>

An event's summary.

=item B<%HtmlSummary%>

An event's summary with all line feeds replaced by C<E<lt>br /E<gt>>.

B<Caution:> The HTML reserved characters C<E<lt>&"E<gt>> will not be
replaced by their substitutes C<&lt;>, C<&amp;>, C<&quot;> and C<&gt;>.

=item B<%E<lt>EPG CategoryE<gt>%>

An event's value of the respective EPG category as specified in
F<epgsearchcats.conf>, like C<%Genre%> or C<%Category%>.

=item B<%Length%>

An event's length in seconds.

=item B<%Status%>

An event's status (the same as C<%T_Status%%V_Status%%R_Status%>).

=item B<%T_Status%>

A timer's status (C<T>, C<t>, or C<R>), else a space.

=item B<%V_Status%>

An event's VPS status, else a space.

=item B<%R_Status%>

An event's running status, else a space.

=back

For the menus of user-defined times and the menu C<Search results>,
there are also:

=over 4

=item B<%ChNr%>

An event's channel number.

=item B<%ChSh%>

The short name of an event's channel.

=item B<%ChLng%>

The long name of an event's channel.

=item B<%ChData%>

The VDR's internal channel representation (e.g., C<S19.2E-1-1101-28106>).

=item B<%Progr%>

A graphical progress bar; not available for the menu C<Search results>.
The F<VDRSymbols> font must be installed to display it.

=item B<%ProgrT2S%>

A progress bar in F<text2skin> style; not available for the menu
C<Search results>.

=back

And, finally, some common variables:

=over 4

=item B<%TimeNow%>

The current time in 'HH:MM' format.

=item B<%DateNow%>

The current date in 'DD.MM.YY' format.

=item B<%DateShNow%>

The current date in 'DD.MM' format.

=item B<%Date_ISO_Now%>

The current date in 'YYYY-MM-DD' format.

=item B<%VideoDir%>

The VDR's video directory (e.g., F</video>).

=item B<%PlugConfDir%>

The VDR's plugin configuration directory (e.g., F</etc/vdr/plugins>).

=item B<%EPGSearchDir%>

The EPGSearch configuration directory (e.g., F</etc/vdr/plugins/epgsearch>)

=item B<%Colon%>

The C<:> character.

=back

You can also use variables for extended EPG categories defined in
F<epgsearchcats.conf> or use your own variables defined in
F<epgsearchuservars.conf>. Variable names are not case sensitive.

An entry consists of up to six table columns, separated with C<|> characters.
The last entry of each table row should declare the table width in characters,
separated with a C<:> character.

When using characters like C<~>, C<-> or C<#> to separate items (e.g.,
C<%Title% ~ %Subtitle%>) with trailing elements being empty, EPGSearch
will attempt to remove orphaned spaces and separators.

You should vary the tabulation-width values to fit your needs, since the look often
depends on the selected skin.

The file F<epgsearchmenu.conf> is not reloaded with every
plugin call, since this is only useful when testing the configuration file itself.
To activate permanent reloading the file during testing a configuration change,
add the start parameter C<−r> or C<−−reloadmenuconf> in the VDR's start script
(e.g., F<runvdr>).

There's a sample F<epgsearchmenu.conf> in the subdirectory F<conf>. To quickly trying out,
copy the file to the EPGSearch configuration directory (e.g., F</etc/vdr/plugins/epgsearch>).

To enable icons from the font F<VDRSymbols>, simply put the line:

=over 4

    WarEagleIcons=1

=back

into F<epgsearchmenu.conf>. The font F<VDRSymbols> is available at
L<http://andreas.vdr-developer.org/fonts/download.html>.

B<Note:> Once a file F<epgsearchmenu.conf> is present and includes
an entry for a certain menu, the default settings for displaying
this menu are ignored.

See also B<epgsearchmenu.conf>(5).

=head1 11. Working with the timer-conflict menu

If a conflict is detected within the periodic background conflict check, an
an OSD message will notify about this conflict. Pressing C<OK> will raise a menu
that displays all relevant conflicts. This menu can also be opened in EPGSearch
navigating to C<Search entries> » C<Actions> » C<Timer conflict check>.

Besides the relevant conflicts (relevance is controlled via the setup options
of EPGSearch), conflicts not classified as important may have been detected as well.
Pressing C<Show all> will display the complete list. The title of the timer-conflict
menu will always displays the number of relevant conflicts and the total number.

The list first displays the time when a conflict appears, followed by all timers
that will be affected. Each timer entry includes the channel number and name, the
timer's priority, and the percentage of how much of the event will be recorded.
Finally, the timer's file entry is displayed.

Selecting a timer's entry and pressing C<OK> or invoking C<Details> opens a new menu
that displays all concurrent timers. This menu allows resolving the conflict by:

=over 2

=item * searching for the repeat of an event

=item * disabling or deleting a timer

=item * changing the timers' start or stop time, or alternatively its priority

=item * executing other commands on this timer

=back

An entry of this menu consists of the C<E<gt>> character to indicate an active timer,
the channel number, the start and stop times, the priority, the number of the
device that will be used for recording (or C<C> for a conflict) and the timer's file
entry. Pressing C<OK> on a timer entry will show its event description, if present.

When returning from this menu, the conflict-overview menu will be updated to see if
a conflict was really resolved. Some changes of a timer in the conflict-details menu
(like modifying start/stop times or deleting a timer) will also bring up the updated
conflict-overview menu.

B<Note:> A "hidden" setup option C<ConflCheckCmd> allows executing a command for each
timer causing a conflict. This command must directly be entered in the VDR's
F<setup.conf> like this:

=over 4

    epgsearch.ConflCheckCmd = system(your_script_handling_the_conflict.sh, any_arguments like %Timer.File%)

Please refer to "12.3 Calling a system command" below for the possible arguments.

=back

The command is evaluated for each timer causing a conflict whenever an automatic
conflict check is performed. The command will not be evaluated when invoking
the conflict check though the OSD.

As an example for its purpose, this mechanism could be employed for forwarding
a timer to another VDR machine in case of a conflict.

=head1 12. User-defined variables

Own variables can be used wherever variables are supported, like
the default recording directory for manually created timers, the
recording directory of a search timer, or in customized EPG menus.
They are defined in the file F<epgsearchuservars.conf>.

A variable has the syntax C<%VariableName%>. Its name can comprise all
alphanumeric characters, but no spaces or other special characters.

Examples for possible names:

=over 4

    %Series%
    %DocuVar1%
    %ThemesSubtitleDate%

=back

Variable names are case-insensitive.

=head2 12.1 Assignment

Variables always get assigned strings whose spaces are retained.
This is illustrated by the following examples:

=over 4

    %Series%=New series~Thrillers

=back

The variable C<%Series%> will be assigned the string "New series~Thrillers".
This can be used arbitrarily:

=over 4

    %Path%=%Series%

=back

The variable C<%Path%> gets the content of the variable C<%Series%> assigned.

=over 4

    %Path%=%Series%~Lost

=back

The variable C<%Path%> contains the string "New series~Thrillers~Lost".

=head2 12.2 Conditional assignment

Simple if-then-else constructs for assignments are supported by means of
conditional expressions C<I<if> ? I<then> : I<else>>. Conditional expressions
cannot contain strings, only variables; spaces are ignored.

=over 4

    %Foo%=Other
    %Variable%=%Path% ? %Path% : %Foo%

=back

For the ternary operator C<?:>, the expression C<%Path% ?> means
"path not empty?". If this is true, C<%Variable%> gets assigned
the content of C<%Path%>, else the content of C<%Foo%>.

Other checks are supported as well:

=over 4

=over 4

=item == equal

=item != not equal

=back

=back

Thus, for example:

=over 4

    %Variable%=%Path%!=5 ? %Path% : %Foo%

=back

The condition C<%Path%!=5 ?> means "is C<%Path%> not equal 5?".

Comparing variables is also feasible:

=over 4

    %Five%=5
    %Variable%=%Path%!=%Five% ? %Path% : %Foo%

=back

=head2 12.3 Calling a system command

External commands can be called during variable evaluation as well.
The returned string will be assigned to the respective variable:

=over 4

    %UserVar%=system(<script-name>[, <parameters>])

=back

Calls the script F<script-name> with the parameters supplied by the optional list
C<parameters>. Such a parameter can be an arbitrary expression, optionally containing
other variables, but no system call or conditional expression.

Example:

=over 4

    %Result%=system(/usr/local/bin/my-script.sh, -t %Title% -s %Subtitle% -u %MyOtherVar%)

=back

Variables used as parameters will be enclosed in single quotes
(apostrophes), if needed.

The script should return a string B<without line feeds>, since their
removal may cause undesired results.
If the script does not return anything, an empty string will be assigned to the
variable C<%Result%>.

=head2 12.4 Calling a TCP service

A TCP service can be called with the following syntax:

=over 4

    %Result%=connect(<address>, <port>, [<data>])

=back

This will connect to C<address> through the given C<port> and pass the optional
C<data>. The parameter C<address> can be an IP address or the domain name of a
TCP service. The result returned by the service must be terminated B<with a
line feed>.

=head2 12.5 Length of arguments

When passing values to the connect or system command, it can be helpful to have
the length of an argument for simple parsing. The length can be retrieved by:

=over 4

    %Result%=length(<any arguments>)

=back

Example:

=over 4

    %TitleLength%=length(%title%)

=back

=head2 12.6 Other variables

Refer to the section "Customizing the EPG menus" for a list of built-in
variables. Furthermore, every variable defined in F<epgsearchcats.conf>
can be used; see B<epgsearchcats.conf>(5).

=head2 12.7 Examples

    # Weekday, Date, Time
    %DateStr%=%time_w% %date% %time%

    # Themes or Subtitle or Date
    %SubtitleDate%=%Subtitle% ? %Subtitle% : %DateStr%
    %ThemesSubtitleDate%=%Themes% ? %Themes% : %SubtitleDate%

    # Calls a script to get a recording path
    %DocuScript%=system(docu.pl, -t %Title% -s %Subtitle% -e %Episode% -th %Themes% -c %Category% -g %Genre%)
    %Docu%=%DocuScript%

=head1 13. E-mail notifications

EPGSearch can send e-mail notifications when timers get added, modified, or
removed by the search-timer thread, or when timer conflicts have been detected.

=head2 13.1 Setting up e-mail notifications

First, copy the script F<sendEmail.pl> to the place where executables are
located (e.g., F</usr/local/bin>) and configure the e-mail accounts in the setup.
Press C<Test> to check if sending and receiving e-mails works. A message like
C<Email successfully sent> should appear at the end of the output.

The content of the e-mails is defined by the files:

=over 4

=item B<F<epgsearchupdmail.templ>>

Template for the notification of search-timer updates.

=item B<F<epgsearchconflmail.templ>>

Template for the notification of timer conflicts.

=back

Sample files are included in the F<conf> directory. Copy them to the EPGSearch
configuration directory (e.g., F</etc/vdr/plugins/epgsearch>) and adapt them as needed.

=head2 13.2 Customizing the notification e-mails

The content of the e-mails can be customized in many ways. E-mails can contain
plain text or HTML (see the sample F<conf/epgsearchupdmail-html.templ>).

=head3 13.2.1 Update-notification e-mails

For an update-notification e-mail, the following sections must be defined:

=over 4

=item B<Subject>

The term to be used as e-mail subject.

=item B<MailBody>

The body of the e-mail. Variables control which information to be inserted
at which location within the body text.

The variable C<%Update.NewTimers%> inserts the list of new timers. Likewise, the
variables C<%Update.ModTimers%>, C<%Update.DelTimers%>, and C<%Update.NewEvents%>
insert the list of changed or deleted timers and event announcements. Their
appearance is controlled by the sections C<Timer> and C<Event>.

=item B<Timer>

Template for the representation of an individual timer. This section is used to
format a timer within a timer list, like in C<%Update.NewTimers%>.

=item B<Event>

Template for the representation of an individual event. This section is used to
format an event within an event list, like in C<%Update.NewEvents%>.

=back

All sections are optional. If, for instance, not using event notifications,
both the sections C<%Update.NewEvents%> in the mail body and the C<Event>
template can be dropped. Nevertheless, the section C<MailBody> must remain.

Each section is enclosed with a pseudo XML tag. Their spelling is not
case-sensitive.

=head4 13.2.1.1 Section C<MailBody>

The following variables can be used in the section C<MailBody>:

=over 4

=item B<%Update.NewTimers%>

Will be replaced with the list of new timers created with this update.
The timers are formatted as defined in the section C<Timer>.

=item B<%Update.CountNewTimers%>

The number of new timers.

=item B<%Update.ModTimers%>

Same as C<%Update.NewTimers%>, but for the modified timers.

=item B<%Update.CountModTimers%>

The number of modified timers.

=item B<%Update.DelTimers%>

Same as C<%Update.NewTimers%>, but for the deleted timers.

B<Note:> A deleted timer possibly has no event assigned to it.
In such a case, all event variables within the C<Timer> section
will be substituted by an empty string.

=item B<%Update.CountDelTimers%>

The number of deleted timers.

=item B<%Update.NewEvents%>

Will be replaced with the list of events to be announced. These events result
from search timers with the action C<Announce by mail>. The events are formatted
as defined in the section C<Event>.

=item B<%Update.CountNewEvents%>

The number of new events.

=item B<%DateNow%>

The current date in 'DD.MM.YY' format.

=item B<%DateShNow%>

The current date in 'DD.MM' format.

=item B<%TimeNow%>

Current time in 'HH:MM' format.

=item B<%Colon%>

The C<:> character.

=back

=head4 13.2.1.2 Section C<Timer>

The following variables can be used in the section C<Timer>:

=over 4

=item B<%Timer.Date%>

The start date of the timer.

=item B<%Timer.Start%>

A timer's start time.

=item B<%Timer.Stop%>

A timer's stop time.

=item B<%Timer.File%>

A timer's recording directory.

=item B<%Timer.ChNr%>

A timer's channel number.

=item B<%Timer.ChSh%>

The short name of a timer's channel.

=item B<%Timer.ChLng%>

The long name of a timer's channel.

=item B<%Timer.Search%>

The search term that created a timer.

=item B<%Timer.SearchID%>

The identifier of the search that created a timer.

=item B<%Timer.LiveID%>

A timer's identifier as used in the front end F<live>.

=item B<%Timer.ModReason%>

The reason for a timer modification in plain text.

=item B<%E<lt>Event VariableE<gt>%>

See "10. Customizing the EPG menus".

=item B<%E<lt>EPG CategoryE<gt>%>

An event's value of the respective EPG category as specified in
F<epgsearchcats.conf>, like C<%Genre%> or C<%Category%>.

=item B<%E<lt>User VariableE<gt>%>

See "12. User-defined variables".

=back

=head4 13.2.1.3 Section C<Event>

The following variables can be used in the section C<Event>:

=over 4

=item B<%Search%>

The search term that triggered the event.

=item B<%SearchID%>

The identifier of the search that triggered the event.

=item B<%E<lt>Event VariableE<gt>%>

See "10. Customizing the EPG menus".

=item B<%E<lt>EPG CategoryE<gt>%>

An event's value of the respective EPG category as specified in
F<epgsearchcats.conf>, like C<%Genre%> or C<%Category%>.

=item B<%E<lt>User VariableE<gt>%>

See "12. User-defined variables".

=back

=head3 13.2.2 Conflict-notification e-mails

For a conflict-notification e-mail, the following sections exist:

=over 4

=item B<Subject>

The term to be used as e-mail subject.

=item B<MailBody>

The body of the e-mail. Variables control which information to be inserted
at which location within the body text.

The variable C<%Conflict.Conflicts%> inserts the list of conflicting times.
The conflicts are formatted as defined in the section C<ConflictsAt>.

B<Note:> More than just one timer conflict can occur for the same time.

=item B<ConflictsAt>

Template for the representation of the time at which one or more conflicts
have occurred.

=item B<ConflTimer>

The description of a conflicting timer.

=back

=head4 13.2.2.1 Section C<MailBody>

The following variables can be used in the section C<MailBody>:

=over 4

=item B<%Conflict.Count%>

The number of all timer conflicts, including both relevant and irrelevant conflicts.

=item B<%Conflict.Conflicts%>

The list of times with conflicting timers.

=back

=head4 13.2.2.2 Section C<ConflictsAt>

The following variables can be used in the section C<ConflictsAt>:

=over 4

=item B<%Conflict.Date%>

The date of the conflict.

=item B<%Conflict.Time%>

The time of the conflict.

=item B<%Conflict.ConflTimers%>

The list of conflicting timers for this time.

=back

=head4 13.2.2.3 Section C<ConflictTimer>

The section C<ConflictTimer> can use the same variables as the section C<Timer>
in an update e-mail (see above).

=head1 14. The F<conf.d> directory

EPGSearch supports a configuration mechanism well-known in Linux. This
applies to the settings of the following configuration files:

=over 2

=item * F<epgsearchuservars.conf>

=item * F<epgsearchdirs.conf>

=item * F<epgsearchmenu.conf>

=item * F<epgsearchcats.conf>

=back

Their settings also be provided by a single file with arbitrary name in
the subdirectory F<conf.d> in the plugin's configuration directory (e.g.,
F</etc/vdr/plugins/epgsearch/conf.d>). This allows quickly testing different
setups by just exchanging files instead of editing them. The format of
files within F<conf.d> is:

=over 4

    [<section name>]
    <settings>
    ...

    [<section name>]
    <settings>
    ...

=back

A C<section name> is one of the following keywords:

=over 2

=item * I<epgsearchuservars>

=item * I<epgsearchdirs>

=item * I<epgsearchmenu>

=item * I<epgsearchcats>

=back

The format of C<settings> is the same as in the corresponding configuration
file. Comments beginning with a C<#> character and blank lines are both allowed.

At startup, EPGSearch first reads its "regular" configuration files and then
inspects the F<conf.d> subdirectory. Variables already defined in other files
can be overwritten, although this is signaled with a warning in the EPGSearch
log file.

=head1 AUTOREN (Man-Pages)

Ursprünglich erstellt von Mike Constabel <epgsearch (at) constabel (dot) net>.

Überarbeitet und an die aktuellen Features von EPGSearch adaptiert durch die
derzeitigen Maintainer.

=head1 PROJEKTSEITE

Das Plugin wird als Projekt auf GitHub geführt:

L<https://github.com/vdr-projects/vdr-plugin-epgsearch/>

=head1 FEHLER MELDEN

Fehlerberichte sowie Feature-Anfragen können über den Bugtracker
des Projekts eingespeist werden:

L<https://github.com/vdr-projects/vdr-plugin-epgsearch/issues/>

=head1 COPYRIGHT und LIZENZ

Copyright © 2004-2010 Christian Wieninger

Copyright © 2011-2025 TomJoad (VDR-Portal) et al.

Dieses Programm ist freie Software. Sie können es unter den Bedingungen
der GNU General Public License, wie von der Free Software Foundation
veröffentlicht, weitergeben und/oder modifizieren, entweder gemäß Version 2
der Lizenz oder (nach Ihrer Option) jeder späteren Version.

Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, dass es
Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, sogar ohne die
implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN BESTIMMTEN
ZWECK. Details finden Sie in der GNU General Public License.

Sie sollten ein Exemplar der GNU General Public License zusammen mit
diesem Programm erhalten haben. Falls nicht, schreiben Sie an die
Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
Oder rufen Sie in Ihrem Browser L<https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
auf.

Der ursprüngliche Autor kann über L<cwieninger@gmx.de> erreicht werden.

Die aktuellen Maintainer können über die Projektseite auf GitHub
(siehe oben) erreicht werden.

Der MD5-Code ist abgeleitet aus dem Message-Digest-Algorithmus MD5
von RSA Data Security, Inc.

=head1 SIEHE AUCH

B<epgsearch>(1),
B<epgsearchblacklists.conf>(5),
B<epgsearchcats.conf>(5),
B<epgsearchchangrps.conf>(5),
B<epgsearchcmds.conf>(5),
B<epgsearchdirs.conf>(5),
B<epgsearchdone.data>(5),
B<epgsearchmenu.conf>(5),
B<epgsearchswitchtimer.conf>(5),
B<epgsearchuservars.conf>(5)