epgsearch(4)
πΈ epgsearch(4) β EPGSearch Version 2.4.6 β¨
okay bestie, so this is the man page for epgsearch, and it literally says epgsearch(4) right up top with EPGSearch Version 2.4.6 so you know exactly what era we're in π
π NAME π
EPGSearch β search timers and replacement of the VDR's default schedules menu π«Ά
β¨ OVERVIEW β¨
So basically the old README got so big it was giving unhinged energy, and this man page is its glow-up replacement π It explains some features and behaviors in detail. Lowkey it's not really a manual though β it's an extended README. No cap. It said so itself. π
π¦ CONTENT π¦
the whole vibe check, in order:
- Using variables in the directory entry of a search timer
- The format of the file
epgsearch.conf - Description of the search process
- How do search timers work?
- How to trigger a search-timer update?
- The sources of the 'Select directory' menu
- Language-dependent commands for the EPG
- Usage from other plugins or scripts
- The SVDRP interface
- Customizing the EPG menus
- Working with the timer-conflict menu
- User-defined variables
- E-mail notifications
- The
conf.ddirectory
π 1. Using variables in the directory entry of a search timer π
When you're using extended EPG information, variables can be part of the directory entry of a search timer. These variables always have the syntax '%Variable%' β that's the whole rule, periodt β¨
The name of a variable corresponds with the internal name of an extended EPG information as specified in the file epgsearchcats.conf; samples can be found in subdirectory conf of the plugin's source directory. iykyk π
Example:
1|Category|Kind|Information,Children,Music,Series,Show,Movie,Sports|3
The category with ID 1 has the internal name 'Category'. So you could refer to it with '%Category%'. Variable names are case-insensitive β so don't stress about the caps, bestie π«Ά
Sample directory entries could look like this:
My Movies~%Category%
Children's Movies~%category%
%CATEGORY%~%genre%
Three more variables are available:
%Title%β Substituted by the name of the event.%Subtitle%β Substituted by the short text of the event.%ChLng%β Substituted by the long name of the channel on which the event is broadcasted.
If neither '%Title%' nor '%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. And if 'Series recording' is set to 'yes' in the search timer, the subtitle will be automatically appended, too. So, the directory entry:
%Category%~%Genre%~%Title%~%Subtitle%
is the same as:
%Category%~%Genre%
if 'Series recording' set to 'yes'. literally the same thing, bestie π
Attention: Title and subtitle will not be appended automatically if one of the variables'%Title%'or'%Subtitle%'is part of the directory specification. This allows forming directory entries like this one:
%Category%~%Genre%~%Title%~%Episode%~%Subtitle%
Furthermore, the following search variables are available in addition:
%Search.Query%β Substituted by the search term of the search timer.%Search.Series%β Substituted by1if the search has the 'Series recording' flag set, or0otherwise.
See also epgsearchuservars.conf(5). π
π 2. The format of the file epgsearch.conf π
Every line within the file represents a search or search timer, comprising the following fields. buckle up, there's 48 of them and I'm not skipping a single one π
1 β Unique identifier (ID)
Integer with a positive value.
2 β Search term ("query")
String specifying the search criterion.
3 β Use time
Flag with values 0 = no, 1 = yes.
4 β Start after [HHMM]
Integer with HH = 0..23, MM = 0..59; other values may result in undefined behavior. β οΈ
5 β Start before [HHMM]
Integer with HH = 0..23, MM = 0..59; other values may result in undefined behavior. β οΈ
6 β Use channel
Enumeration with values 0 = no, 1 = interval, 2 = channel group, 3 = FTA (free-to-air) only.
7 β Channel selection
if 'use channel' = 1:
String with 'ChannelID' or 'MinChannelID'|'MaxChannelID'; the channel identifiers must conform to the VDR notation (e.g., 'S19.2E-1-1019-10301').
Attention: Please check the range settings of your search timers after changing the sequence of the channels! π«£
if 'use channel' = 2:
String referring to a previously configured channel-group name.
8 β Match case
Flag with values 0 = no, 1 = yes.
9 β Search mode
Enumeration with the following values:
0= phrase1= all words2= at least one word3= match exactly4= regular expression5= fuzzy search (tolerance in field42; not available for extended EPG categories)
See "Description of the search process" for how these modes control the search.
10 β Use title
Flag with values 0 = no, 1 = yes.
11 β Use subtitle
Flag with values 0 = no, 1 = yes.
12 β Use description
Flag with values 0 = no, 1 = yes.
13 β Use duration
Flag with values 0 = no, 1 = yes.
14 β Minimum duration [HHMM]
Integer with HH = 0..23, MM = 0..59; other values may result in undefined behavior. β οΈ
15 β Maximum duration [HHMM]
Integer with HH = 0..23, MM = 0..59; other values may result in undefined behavior. β οΈ
16 β Use as search timer
Enumeration with the following values:
0= no1= yes2= time span (fields48and49)
17 β Use day of week
Flag with values 0 = no, 1 = yes.
18 β Day of week
Integer value from β127 to 6. The encoding is twofold:
if dow β₯ 0: individual weekday
Enumeration with values 0 = Sunday, 1 = Monday, ..., 6 = Saturday.
if dow < 0: set of weekdays
Integer in which the bits of βdow represent the weekdays. Bit masks result from shifting 0x01 by a weekday's enumeration value:
0x01 = Sunday
0x02 = Monday
0x04 = Tuesday
0x08 = Wednesday
0x10 = Thursday
0x20 = Friday
0x40 = Saturday
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 π₯
19 β Series recording
Flag with values 0 = no, 1 = yes.
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.
21 β Priority of recording
Integer value from 0 to 99.
22 β Lifetime of recording [days]
Integer value from 0 to 99.
23 β Margin at start [minutes]
Integer with a positive value.
24 β Margin at stop [minutes]
Integer with a positive value.
25 β Use VPS
Flag with values 0 = no, 1 = yes.
26 β Action
Enumeration with the following values:
0= record1= announce by OSD (no timer)2= switch only (no timer)3= announce by OSD and switch (no timer)4= announce by e-mail5= inactive record
27 β Use extended EPG information
Flag with values 0 = no, 1 = yes.
28 β Extended EPG information values
List of extended EPG category data, each represented by a tuple of:
28.1 β Identifier
Unique identifier of the extended EPG category as specified in epgsearchcats.conf.
28.2 β Category values
Comma-separated list of values as specified for the EPG category in epgsearchcats.conf. Spaces around values are ignored. A ':' character, like in '16:9', must be encoded as '!^colon^!'.
The '|' character separates adjacent category tuples, whereas '#' separates ID and category names.
Example: '1#Movie, Series|2#Horror|8#16!^colon^!9'
29 β Avoid repeats
Flag with values 0 = no, 1 = yes.
30 β Allowed repeats
Integer value from 0 to 99.
31 β Compare title (when testing for repeats)
Flag with values 0 = no, 1 = yes.
32 β Compare subtitle (when testing for repeats)
Enumeration with value 0 = no, 1 = yes, 2 = allow empty.
33 β Compare summary (when testing for repeats)
Flag with values 0 = no, 1 = yes.
34 β Compare categories (when testing for repeats)
Integer in which each bit represents an extended EPG category. The first EPG category specified in epgsearchcats.conf is represented by bit 0 (0x01), the second by bit 1 (0x02), etc. A nonzero value enables comparison.
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. π
35 β Only repeats within ... days
Integer value from 0 to 999.
36 β Delete recordings after ... days
Integer value from 0 to 999.
37 β Keep ... recordings
Integer value from 0 to 999.
38 β Switch ... minutes before start
Integer value from 0 to 99; only considered if 'action' = 2.
39 β Pause when ...recordings exist
Integer value from 0 to 999.
40 β Blacklist usage mode
Enumeration with values 0 = only global, 1 = selection, 2 = all, 3 = none.
41 β Blacklist selection
List of blacklist identifiers, separated by '|' characters; only considered if 'blacklist usage mode' = 1.
42 β Fuzzy tolerance
Integer value from 1 to 9, serving as threshold for fuzzy searching; only considered if 'search mode' = 5.
43 β Use in favorites menu
Flag with values 0 = no, 1 = yes.
44 β Result menu layout for favorites menu
Integer referencing a search-result template specified in epgsearchmenu.conf. The value is the index (starting at 0) within all entries having a prefix of 'MenuSearchResults'; see "10. Customizing the EPG menus" in epgsearch(4) for details.
Note: The field is only of relevance if multiple search-result templates have been specified.
45 β Auto delete mode
Enumeration with the following values:
0= don't delete the search timer1= delete after a number of recordings (field46)2= delete after a number of days after the first recording (field47)
46 β Delete after ... recordings
Integer value from 0 to 999; only considered if 'auto delete mode' = 1.
47 β Delete after ... days after first recording
Integer value from 0 to 999; only considered if 'auto delete mode' = 2.
48 β First day (use as search timer from)
Date and time in 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. β
Okay so continuing the list of fields, bestie β we're at 49 and it's only getting more iconic β¨
49β Last day (use as search timer until) π β date and time in Epoch encoding (i.e., seconds since1970-01-01 00:00 UTC) until which the search timer is active. A value of0disables the check.
Note bestie: any Epoch value can be supplied. So like, providing a time within a day (instead of midnight) will keep the timer active until that intra-day time has been reached. No cap π
50β Matching mode of extended EPG information β an enumeration, and the values are:0= all selected categories1= all except missing categories2= at least one category
This lets you include events with missing or just some matching categories. But ngl, without other sufficiently limiting criteria, this could yield a huge number of results π
51β Unmute sound β flag with values0= no,1= yes; only considered if'action'=2or3.52β Minimum match in percent β integer value from1to100, specifying the minimum match required to avoid repeats when summaries are to be compared; only considered if'compare summary'=1.53β Content descriptors β a string with content descriptors to be checked. Content descriptors are values from0to255(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.
Example: content identifiers 17 (detective, thriller), 20 (comedy) and 176 (original language) are encoded as '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 π
54β Compare date (when testing for repeats) β enumeration with the values0= no,1= same day,2= same week,3= same month.55β Matching mode of content categories β enumeration with these values:0= all selected descriptors1= any selected descriptor2= some selected descriptor per group
Modes 0 and 1 instantly match across all category groups but nevertheless use the matching mode of field 56 for checking the special characteristics. So combos 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.
56β Matching mode of special characteristics β enumeration with values0= all selected descriptors,1= any selected descriptor; only considered if'content descriptors'is not empty.57β Use parental rating β flag with values0= no,1= yes.58β Minimum parental rating β integer value from0to18.59β Maximum parental rating β integer value from0to18.
A search timer's entry is considered valid if it covers at least the first 11 fields. Like, minimum viable timer, periodt β¨
The fields ("parameters") of a search timer are separated by ':' characters. Which means a ':' character in strings, like the search term or the directory, will be encoded as a '|' character. And if a '|' character should be part of the string as well, like in regular expressions, it will be encoded as '!^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:
1:My favorite series: 0::: 0::0:0
^^^^
Furthermore, leading and trailing whitespace around a field value is discarded. This implies, however, that strings cannot start or end with whitespace π
Note: strings within fields must not be enclosed in quotation marks or apostrophes, even if this should be indicated in a field's description. Those characters have just been inserted during compilation of this man page. Fr fr, do not add quotes π
See also epgsearch.conf(5).
β¨ 3. Description of the search process β¨
Okay so first, a temporary search text is created for each broadcast, in which title, subtitle and description are separated by '~' characters:
title~subtitle~description
Depending on the settings of 'use title', 'use subtitle' and 'use description', these components are either inserted or remain empty.
If '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:
Phrase Matches if the search term is found anywhere in the search text.
All words At least one word First, the search term will be split into single words; delimiters are spaces and one of the ',;|~' characters. Second, the search succeeds if at least one word, or all words, appear in the search text.
Match exactly Matches if search term and search text are identical.
Regular expression The search is performed with a regular expression. Two standards are supported: extended POSIX and Perl compatible regular expressions (PCRE) (see INSTALL).
Note: unlike in Perl, leading and trailing '/' characters are not required for the search term π¦
Fuzzy Compares the search term based upon the Levenshtein-Distance algorithm. The value of the field 'fuzzy tolerance' determines how much deviation is acceptable.
Note: the search term is limited to 32 characters when using the fuzzy mode πΈ
If the search was successful so far, the other criteria (start time, duration, weekday, etc.) are checked. Slaaay, one step at a time π
π 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. Literally so considerate ππ«Ά
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. Not me respecting your hand-tuned settings π
If '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. Bestie gets a whole notification system fr fr π
π 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:
Periodically The search timers will be updated a few seconds after the VDR has started. Once finished, the setup option 'Update interval [min]' determines in which intervals future updates shall be done.
Externally The thread observes the file '.epgsearchupdate' in the plugin's configuration directory. After executing:
touch /path_to_file/.epgsearchupdate
an update will be performed. This offers a simple way to trigger an update, for example when running a script π
Internally Calling 'Actions' Β» 'Trigger search timer update' or pressing 3 in the menu 'Search entries' will also trigger an update.
By other plugins The service '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 π¦
π 6. The sources of the '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:
- current recording directories
- current timer directories
- directories used in search timers
- directories specified in
epgsearchdirs.conf, seeepgsearchdirs.conf(5) - entries in the VDR's
folders.conf
The menu merges these directories and displays only distinct directories. The key 'yellow' allows changing the level of the directories shown. Should there be items containing EPG category variables like '%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 '%Title%' or %Subtitle, the timer's 'File' entry gets cleared, since title or subtitle already included in the 'Directory' item. Lowkey genius tbh π
This list can also be accessed via the SVDRP command 'LSRD' π
7. Language-dependent commands for the EPG β¨
Okay so if you want a language-dependent list of commands, it's actually so easy, bestie: just translate your current epgsearchcmds.conf into your fave OSD language and save it as epgsearchcmds-<LOC>.conf, where <LOC> is the locale's code from i18n.c:
{ "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
}
If more codes are listed for a language, like 'eng,dos', choose one of them. No stress, just pick your fave π
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 epgsearchcmds.conf file instead. Fallback queen behavior, honestly π
See also epgsearchcmds.conf(5).
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, and both are lowkey iconic:
8.1. File-based (intended for use in scripts) π
So for this one, simply create the file .epgsearchrc in the plugin's configuration directory with these lines in it:
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
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. It's giving self-cleaning main character energy π§
Later on, another search can be triggered by means of the SVDRP interface. Supposing that the key 'green' has been assigned to EPGSearch (see epgsearch(1), chapter 5), just call EPGSearch via svdrpsend:
svdrpsend HITK green
A sample script recep.sh that searches for the repeats of a recording is provided in the subdirectory scripts of EPGSearch. Go off, script bestie π
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:
- searching the EPG for some criteria and displaying the list of results
- invoking the extended timer-edit menu
A quick-and-dirty sample plugin provided in the EPGSearch source directory (vdr-epgsearchclient-0.0.1.tgz) demonstrates the usage. Ngl, that little sample is doing the most so you don't have to πβ¨
9. The SVDRP interface π»β¨
okay bestie, this is the part where EPGSearch lets the outside world in β it implements an SVDRP interface, and you can slide into it like this:
svdrpsend PLUG epgsearch LSTS
The next little sections walk you through every command chilling at that interface. Buckle up π
9.1 Search management ποΈ
LSTS [ID]β lists all searches, or just the one with the ID you handed it. The format of the data it gives back is the same as inepgsearch.conf(see above, bestie).NEWS settingsβ adds a shiny new search. The data format of settings is identical to the one used inepgsearch.conf(see above).
The unique identifier (field 1) gets ignored β EPGSearch always assigns the next free identifier and tells you about it in the response:
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
EDIS parametersβ modifies an existing search. The data format of parameters is identical to the one used inepgsearch.conf(see above). The identifier in field 1 is what specifies which search you're modifying.
Note: an empty field (::) is just ignored, no drama. But the values of the fields 'search', 'directory' and 'content descriptors' will be cleared if no values have been supplied. So yeah β mind that π
MODS ID ON|OFFβ flips the option 'Use as search timer' on or off. That's it, that's the whole job πDELS IDβ deletes the search with the supplied ID. bye bestie π«ΆSETS ON|OFFβ starts (switches 'ON') or stops (switches 'OFF') the search-timer background thread. The engine room switch, fr fr.UPDS [OSD]β updates searches and search timers. If you pass the optional keywordOSD, you get an OSD message once the update is done β little victory screen πUPDTβ reloads the fileepgsearch.conf, like, for instance after some external tool went and modified it behind your back.UPDDβ reloads the fileepgsearchdone.data, same energy β for when an external tool has been editing it.FIND <parameters>β searches the EPG for matching events. The data format of parameters is identical to the one used inepgsearch.conf(see above).
It returns one line per found event, formatted as the VDR's 'NEWT' command. That comprises these fields:
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
Example:
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
A search result can thus instantly be used to create a timer for the corresponding event β no cap, it just hands you the goods π
Note: if not controlled by VPS, the date and start/stop times include the start/stop margins specified in the parameters. Keep that in mind, okay?
QRYS ID[|ID|...]β retrieves the results for a search with the supplied ID. You can pass multiple IDs, separated by|characters, and it's totally fine β¨
Returns one line per ID, using this format:
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)
Example:
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
QRYS parametersβ retrieves the results for a search with the given parameters, ignoring the unique identifier in field 1. Same command, parameter flavor πQRYF [hours]β retrieves the results for the favorites menu; see 'QRYS' for the data format of the results. The optional parameter tells it how many hours to inspect, and it defaults to 24 hours β°MENU [NOW|PRG|SUM]β invokes an EPGSearch menu or the summary of the current event:NOWβ ongoing broadcastsPRGβ schedule of the current channelSUMβ description of the current event
Caution: the menu will only be displayed if no other menu is open at that time β otherwise the currently shown menu gets closed instead. So this command is not fully deterministic. You've been warned π
9.2 Channel-group management πΊ
LSTC [name]β lists all channel groups, or just the one with the supplied name. The format of the returned data is the same as inepgsearchchangrps.conf.NEWC settingsβ creates a new channel group. The data format of settings is the same as inepgsearchchangrps.conf.EDIC settingsβ modifies an existing channel group. The data format of settings is the same as inepgsearchchangrps.conf.RENC old-name|new-nameβ renames an existing channel group. glow-up time πDELC nameβ deletes an existing channel group. gone, reduced to atoms π¦
9.3 Blacklist management π«
LSTB [ID]β retrieves all blacklists, or just the one with the supplied ID. The format of the returned data is the same as inepgsearchblacklists.conf.NEWB settingsβ adds a new blacklist. The data format of settings is the same as inepgsearchblacklists.conf.
The unique identifier (field 1) gets ignored β EPGSearch always assigns the next free identifier and reports it in the response:
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
DELB IDβ deletes the blacklist with the supplied ID.EDIB settingsβ modifies an existing blacklist. The data format of settings is the same as inepgsearchblacklists.conf. The identifier in field 1 specifies which blacklist is getting modified.
Note: an empty field (::) is ignored. However, the values of the fields 'search' and 'content descriptors' will be cleared if no values have been supplied. (Yep, slightly different list thanEDISβ read carefully, bestie π)
9.4 Search-template management π
LSTT [ID]β lists all search templates, or just the one with the passed ID. The format of the returned data is the same as inepgsearch.conf(see above).NEWT settingsβ adds a new search template. The data format of settings is the same as inepgsearch.conf(see above).
The value of the search identifier (field 1) gets ignored β EPGSearch always assigns the next free identifier and reports it in the response:
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
EDIT settingsβ modifies an existing search template. The data format of settings is the same as inepgsearch.conf(see above). The identifier in field 1 specifies the search template to be modified.
Note: an empty field (::) is ignored. However, the values of the fields 'search', 'directory' and 'content descriptors' will be cleared if no values have been supplied. Same caveat energy asEDISπ
DELT IDβ deletes the search template with the supplied ID.DEFT [ID]β returns the ID of the default search template. When you supply an ID, the corresponding search template gets set as the new default π
9.5 Extended EPG categories πΈ
LSTE [ID]β lists the extended EPG categories defined inepgsearchcats.conf, or just the one with the supplied ID. The format of the returned data is the same as inepgsearchcats.conf.
9.6 Timer conflicts βοΈ
LSCC [REL]β returns the current timer conflicts. With the optionREL, only relevant conflicts are listed. The list of results looks like this example of two timer conflicts at a given time:
1190232780:152|30|50#152#45:45|10|50#152#45
1190232780 is the time of the conflict in 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.
152|30|50#152#45 is the description of the first conflicting timer, and it breaks down like this:
152is VDR's ID of this timer as returned by the VDR's 'LSTT' command30is the percentage of recording that would be done (0..100)50#152#45is the list of all timers involved in this conflict
45|10|50#152#45 describes the another conflict for this point of time. π€ (yes, the drama of it all β two timers, one time slot, chaos)
9.7 Miscellaneous β¨
LSRDβ lists all recording directories used in recordings, timers, search timers, or that are defined inepgsearchdirs.conf. A full tour of your dirs ποΈSETP [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:
ShowFavoritesMenuUseSearchTimersDefRecordingDirAddSubtitleToTimerModeDefPriorityDefLifetimeDefMarginStartDefMarginStop
And that's the SVDRP toolbox, bestie β every command, every field, every caveat, all accounted for π (more coming, don't you worry)
β¨ 10. Customizing the EPG menus β¨
okay bestie, this is the glow-up zone π
the file epgsearchmenu.conf, sitting in the EPGSearch config directory, stores all the settings for customizing the EPG menus. Each line configures the display of a certain menu, and the entries specify the layouts for these menus:
MenuWhatsOnNowβ template for the menu 'Now'.MenuWhatsOnNextβ template for the menu 'Next'.MenuWhatsOnElseβ template for the menu of a user-defined time.MenuScheduleβ template for the menu 'Schedule'.MenuSearchResultsβ template for the menu 'Search results'.MenuFavoritesβ template for the menu 'Favorites'.
For example:
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
The entry MenuWhatsOnNow tells EPGSearch how to format a line for the menu 'Now': the menu's line will start with the channel number, followed by a progress bar in text2skin style, a single space, the start time, the timer status, the value of the EPG category named 'Category' (e.g., "Movie") and, finally, the title and subtitle. iconic behavior, honestly β¨
The values for MenuWhatsOnNext, MenuWhatsOnElse, MenuSchedule, MenuSearchResults and MenuFavorites specify the menu settings for 'Next', the menu of a user-defined time, 'Schedule', 'Search results', and 'Favorites', respectively. Without a corresponding entry, EPGSearch uses a menu's default layout. no stress π«Ά
The entry 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:
MenuSearchResultsTip of the Day=%chnr%:3|%time_w%:4|%t_status%:3|%genre%:10|%title%%colon% %subtitle%:35
This will result in an additional menu item 'Result menu layout' in the menu 'Edit search' that allows choosing between the menu's default template and own templates. For the example above, 'Tip of the Day' will be listed as additional option, since EPGSearch simply strips the prefix MenuSearchResults. When displaying the search results, the chosen layout will be used instead of the default one. cute little customization hack, iykyk π
The following variables exist (case ignored):
%Time%β an event's start time inHH:MMformat β°%TimeEnd%β an event's end time inHH:MMformat.%Time_D%β an event's start date inDDformat.%Time_W%β name of the weekday on which an event starts.%Time_Lng%β an event's start date and time in Epoch encoding (i.e., seconds since1970-01-01 00:00 UTC).%TimeSpan%β time span til the start of an event (like'in 15m') or the time an event is already running (like'10m').%Date%β an event's start date inDD.MM.YYformat.%DateSh%β an event's start date inDD.MMformat.%Date_ISO%β an event's start date inYYYY-MM-DDformat.%Day%β an event's start day (1..31).%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.%Month%β an event's start month (1..12).%Year%β an event's start year (1970..2038, or even later).%EventID%β an event's numeric identifier.%LiveEventID%β an event's identifier as used in the front end live.%Title%β an event's title.%Subtitle%β an event's subtitle.%Summary%β an event's summary.%HtmlSummary%β an event's summary with all line feeds replaced by'<br />'. Caution: the HTML reserved characters<&">will not be replaced by their substitutes<,&,"and>. this is a little βhandle with careβ moment π%<EPG Category>%β an event's value of the respective EPG category as specified inepgsearchcats.conf, like%Genre%or%Category%.%Length%β an event's length in seconds.%Status%β an event's status (the same as%T_Status%%V_Status%%R_Status%).%T_Status%β a timer's status ('T','t', or'R'), else a space.%V_Status%β an event's VPS status, else a space.%R_Status%β an event's running status, else a space.
For the menus of user-defined times and the menu 'Search results', there are also:
%ChNr%β an event's channel number.%ChSh%β the short name of an event's channel.%ChLng%β the long name of an event's channel.%ChData%β the VDR's internal channel representation (e.g.,'S19.2E-1-1101-28106').%Progr%β a graphical progress bar; not available for the menu 'Search results'. The VDRSymbols font must be installed to display it.%ProgrT2S%β a progress bar in text2skin style; not available for the menu 'Search results'.
And, finally, some common variables:
%TimeNow%β the current time inHH:MMformat.%DateNow%β the current date inDD.MM.YYformat.%DateShNow%β the current date inDD.MMformat.%Date_ISO_Now%β the current date inYYYY-MM-DDformat.%VideoDir%β the VDR's video directory (e.g.,/video).%PlugConfDir%β the VDR's plugin configuration directory (e.g.,/etc/vdr/plugins).%EPGSearchDir%β the EPGSearch configuration directory (e.g.,/etc/vdr/plugins/epgsearch)%Colon%β the':'character.
You can also use variables for extended EPG categories defined in epgsearchcats.conf or use your own variables defined in epgsearchuservars.conf. Variable names are not case sensitive.
An entry consists of up to six table columns, separated with | characters. The last entry of each table row should declare the table width in characters, separated with a : character.
When using characters like ~, - or # to separate items (e.g., %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. lowkey the skin is the main character here π
The file 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 βr or ββreloadmenuconf in the VDR's start script (e.g., runvdr).
There's a sample epgsearchmenu.conf in the subdirectory conf. To quickly try it out, copy the file to the EPGSearch configuration directory (e.g., /etc/vdr/plugins/epgsearch). instant trial run, no cap π§
To enable icons from the font VDRSymbols, simply put the line:
WarEagleIcons=1
into epgsearchmenu.conf. The font VDRSymbols is available at <http://andreas.vdr-developer.org/fonts/download.html>.
Note: once a file epgsearchmenu.conf is present and includes an entry for a certain menu, the default settings for displaying this menu are ignored. your custom layout ate, periodt π₯
See also epgsearchmenu.conf(5).
π₯ 11. Working with the timer-conflict menu π₯
okay so if a conflict is detected within the periodic background conflict check, an OSD message will notify about this conflict. Pressing 'OK' will raise a menu that displays all relevant conflicts. This menu can also be opened in EPGSearch navigating to 'Search entries' Β» 'Actions' Β» 'Timer conflict check'. very βwe need to talkβ energy π
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 'Show all' will display the complete list. The title of the timer-conflict menu will always display 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 'OK' or invoking 'Details' opens a new menu that displays all concurrent timers. This menu allows resolving the conflict by:
- searching for the repeat of an event
- disabling or deleting a timer
- changing the timers' start or stop time, or alternatively its priority
- executing other commands on this timer
An entry of this menu consists of the > 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' for a conflict) and the timer's file entry. Pressing 'OK' on a timer entry will show its event description, if present. little info drop, very demure π
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.
Note: a "hidden" setup optionConflCheckCmdallows executing a command for each timer causing a conflict. This command must directly be entered in the VDR'ssetup.conflike this:
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.
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 through 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. forwarding the drama to another VDR, we love to see it π
πΈ 12. User-defined variables πΈ
Okay bestie, this is where it gets custom. You can use your own variables anywhere variables are supported β like the default recording directory for manually created timers, the recording directory of a search timer, or inside customized EPG menus. They live in the file epgsearchuservars.conf. π
A variable has the syntax %VariableName%. Its name can comprise all alphanumeric characters, but no spaces or other special characters.
Examples for possible names:
%Series%
%DocuVar1%
%ThemesSubtitleDate%
Variable names are case-insensitive. (so %Series% and %series% are the same vibe, no cap π)
π 12.1 Assignment
Variables always get assigned strings whose spaces are retained. This is illustrated by the following examples:
%Series%=New series~Thrillers
The variable %Series% will be assigned the string "New series~Thrillers". This can be used arbitrarily:
%Path%=%Series%
The variable %Path% gets the content of the variable %Series% assigned.
%Path%=%Series%~Lost
The variable %Path% contains the string "New series~Thrillers~Lost".
β¨ 12.2 Conditional assignment
Simple if-then-else constructs for assignments are supported by means of conditional expressions if ? then : else. Conditional expressions cannot contain strings, only variables; spaces are ignored. π
%Foo%=Other
%Variable%=%Path% ? %Path% : %Foo%
For the ternary operator ?:, the expression %Path% ? means "path not empty?". If this is true, %Variable% gets assigned the content of %Path%, else the content of %Foo%.
Other checks are supported as well:
==β equal!=β not equal
Thus, for example:
%Variable%=%Path%!=5 ? %Path% : %Foo%
The condition %Path%!=5 ? means "is %Path% not equal 5?".
Comparing variables is also feasible:
%Five%=5
%Variable%=%Path%!=%Five% ? %Path% : %Foo%
π¦ 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:
%UserVar%=system(<script-name>[, <parameters>])
Calls the script script-name with the parameters supplied by the optional list parameters. Such a parameter can be an arbitrary expression, optionally containing other variables, but no system call or conditional expression.
Example:
%Result%=system(/usr/local/bin/my-script.sh, -t %Title% -s %Subtitle% -u %MyOtherVar%)
Variables used as parameters will be enclosed in single quotes (apostrophes), if needed.
The script should return a string 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 %Result%.
π§ 12.4 Calling a TCP service
A TCP service can be called with the following syntax:
%Result%=connect(<address>, <port>, [<data>])
This will connect to address through the given port and pass the optional data. The parameter address can be an IP address or the domain name of a TCP service. The result returned by the service must be terminated with a line feed. periodt. π₯
π 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:
%Result%=length(<any arguments>)
Example:
%TitleLength%=length(%title%)
π 12.6 Other variables
Refer to the section "Customizing the EPG menus" for a list of built-in variables. Furthermore, every variable defined in epgsearchcats.conf can be used; see epgsearchcats.conf(5). iykyk π«
π 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%
π 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. Yes bestie, it'll slide into your inbox. π¬
π 13.1 Setting up e-mail notifications
First, copy the script sendEmail.pl to the place where executables are located (e.g., /usr/local/bin) and configure the e-mail accounts in the setup. Press 'Test' to check if sending and receiving e-mails works. A message like 'Email successfully sent' should appear at the end of the output. π«Ά
The content of the e-mails is defined by the files:
epgsearchupdmail.templβ Template for the notification of search-timer updates.epgsearchconflmail.templβ Template for the notification of timer conflicts.
Sample files are included in the conf directory. Copy them to the EPGSearch configuration directory (e.g., /etc/vdr/plugins/epgsearch) and adapt them as needed.
β¨ 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 conf/epgsearchupdmail-html.templ). π»β¨
πΈ 13.2.1 Update-notification e-mails
For an update-notification e-mail, the following sections must be defined:
Subjectβ The term to be used as e-mail subject.MailBodyβ The body of the e-mail. Variables control which information to be inserted at which location within the body text. The variable%Update.NewTimers%inserts the list of new timers. Likewise, the variables%Update.ModTimers%,%Update.DelTimers%, and%Update.NewEvents%insert the list of changed or deleted timers and event announcements. Their appearance is controlled by the sections'Timer'and'Event'.Timerβ Template for the representation of an individual timer. This section is used to format a timer within a timer list, like in%Update.NewTimers%.Eventβ Template for the representation of an individual event. This section is used to format an event within an event list, like in%Update.NewEvents%.
All sections are optional. If, for instance, not using event notifications, both the sections %Update.NewEvents% in the mail body and the 'Event' template can be dropped. Nevertheless, the section 'MailBody' must remain.
Each section is enclosed with a pseudo XML tag. Their spelling is not case-sensitive.
π 13.2.1.1 Section 'MailBody'
The following variables can be used in the section 'MailBody':
%Update.NewTimers%β Will be replaced with the list of new timers created with this update. The timers are formatted as defined in the section'Timer'.%Update.CountNewTimers%β The number of new timers.%Update.ModTimers%β Same as%Update.NewTimers%, but for the modified timers.%Update.CountModTimers%β The number of modified timers.%Update.DelTimers%β Same as%Update.NewTimers%, but for the deleted timers.
Note: A deleted timer possibly has no event assigned to it. In such a case, all event variables within the 'Timer' section will be substituted by an empty string.
%Update.CountDelTimers%β The number of deleted timers.%Update.NewEvents%β Will be replaced with the list of events to be announced. These events result from search timers with the action'Announce by mail'. The events are formatted as defined in the section'Event'.%Update.CountNewEvents%β The number of new events.%DateNow%β The current date in'DD.MM.YY'format.%DateShNow%β The current date in'DD.MM'format.%TimeNow%β Current time in'HH:MM'format.%Colon%β The':'character.
π¦ 13.2.1.2 Section 'Timer'
The following variables can be used in the section 'Timer':
%Timer.Date%β The start date of the timer.%Timer.Start%β A timer's start time.%Timer.Stop%β A timer's stop time.%Timer.File%β A timer's recording directory.%Timer.ChNr%β A timer's channel number.%Timer.ChSh%β The short name of a timer's channel.%Timer.ChLng%β The long name of a timer's channel.%Timer.Search%β The search term that created a timer.%Timer.SearchID%β The identifier of the search that created a timer.%Timer.LiveID%β A timer's identifier as used in the front end live.%Timer.ModReason%β The reason for a timer modification in plain text.%<Event Variable>%β See "10. Customizing the EPG menus".%<EPG Category>%β An event's value of the respective EPG category as specified inepgsearchcats.conf, like%Genre%or%Category%.%<User Variable>%β See "12. User-defined variables".
π§ 13.2.1.3 Section 'Event'
The following variables can be used in the section 'Event':
%Search%β The search term that triggered the event.%SearchID%β The identifier of the search that triggered the event.%<Event Variable>%β See "10. Customizing the EPG menus".%<EPG Category>%β An event's value of the respective EPG category as specified inepgsearchcats.conf, like%Genre%or%Category%.%<User Variable>%β See "12. User-defined variables".
π 13.2.2 Conflict-notification e-mails
For a conflict-notification e-mail, the following sections exist:
Subjectβ The term to be used as e-mail subject.MailBodyβ The body of the e-mail. Variables control which information to be inserted at which location within the body text. The variable%Conflict.Conflicts%inserts the list of conflicting times. The conflicts are formatted as defined in the section'ConflictsAt'.
Note: More than just one timer conflict can occur for the same time. π
ConflictsAtβ Template for the representation of the time at which one or more conflicts have occurred.ConflTimerβ The description of a conflicting timer.
π 13.2.2.1 Section 'MailBody'
The following variables can be used in the section 'MailBody':
%Conflict.Count%β The number of all timer conflicts, including both relevant and irrelevant conflicts.%Conflict.Conflicts%β The list of times with conflicting timers.
π 13.2.2.2 Section 'ConflictsAt'
The following variables can be used in the section 'ConflictsAt':
%Conflict.Date%β The date of the conflict.%Conflict.Time%β The time of the conflict.%Conflict.ConflTimers%β The list of conflicting timers for this time.
π 13.2.2.3 Section 'ConflictTimer'
The section 'ConflictTimer' can use the same variables as the section 'Timer' in an update e-mail (see above).
π 14. The conf.d directory π
okay bestie so EPGSearch does that very Linux thing where config lives in a conf.d-style drop-in directory, and honestly? iconic. β¨ This applies to the settings of these config files:
epgsearchuservars.confepgsearchdirs.confepgsearchmenu.confepgsearchcats.conf
Their settings can also be provided by a single file with an arbitrary name sitting in the conf.d subdirectory of the plugin's config directory (like /etc/vdr/plugins/epgsearch/conf.d). The whole point? You can swap configs in and out for quick testing of different setups instead of hand-editing them like a peasant. π
The format of files inside conf.d is:
[<section name>]
<settings>
...
[<section name>]
<settings>
...
A section name has to be one of these keywords:
epgsearchuservarsepgsearchdirsepgsearchmenuepgsearchcats
The format of settings is exactly the same as in the matching configuration file. Comments starting with a # character and blank lines are both allowed β go off, honestly. π¦
At startup, EPGSearch first reads its "regular" configuration files and then inspects the conf.d subdirectory. Variables already defined in other files can be overwritten, though this gets flagged with a warning in the EPGSearch log file. Not me being nosy in the logs β it's literally just a heads up. π
πΈ AUTOREN (Man-Pages) πΈ
Originally created by Mike Constabel <epgsearch (at) constabel (dot) net>.
Reworked and adapted to the current features of EPGSearch by the current maintainers.
π PROJEKTSEITE π
The plugin is run as a project on GitHub:
https://github.com/vdr-projects/vdr-plugin-epgsearch/
π¦ FEHLER MELDEN π¦
Bug reports and feature requests can be submitted via the project's bug tracker:
https://github.com/vdr-projects/vdr-plugin-epgsearch/issues/
π COPYRIGHT und LIZENZ π
Copyright Β© 2004-2010 Christian Wieninger
Copyright Β© 2011-2025 TomJoad (VDR-Portal) et al.
This program is free software. You can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. β¨
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, even without the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. The details are in the GNU General Public License. (read it, bestie, it's giving required reading π)
You should have received a copy of the GNU General Public License along with this program. If not, write to the Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. Or open https://www.gnu.org/licenses/old-licenses/gpl-2.0.html in your browser.
The original author can be reached at cwieninger@gmx.de.
The current maintainers can be reached via the project page on GitHub (see above).
The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
π SIEHE AUCH π
epgsearch(1)epgsearchblacklists.conf(5)epgsearchcats.conf(5)epgsearchchangrps.conf(5)epgsearchcmds.conf(5)epgsearchdirs.conf(5)epgsearchdone.data(5)epgsearchmenu.conf(5)epgsearchswitchtimer.conf(5)epgsearchuservars.conf(5)
okay that's the whole page, we made it, bestie!! π«Ά This one's perl v5.40.1 flavoured and stamped 2026-04-19, filed under epgsearch(4) β go forth and search the EPG like the main character you are ππ
π¦ where this page comes from
- ubuntu stonking: vdr-plugin-epgsearch 2.4.6-1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms