mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
The files "commands.conf" and "reccmd.conf" can now contain nested lists of commands
This commit is contained in:
parent
0889960232
commit
86291b6205
4
HISTORY
4
HISTORY
@ -6276,7 +6276,7 @@ Video Disk Recorder Revision History
|
||||
- Fixed plugin arguments corruption with glibc 2.11 on x86_64 (thanks to
|
||||
Anssi Hannula).
|
||||
|
||||
2010-01-30: Version 1.7.12
|
||||
2010-01-31: Version 1.7.12
|
||||
|
||||
- Changed the EVCONTENTMASK_* macros to enums and changed "mask" to "group".
|
||||
- Updated the Estonian OSD texts (thanks to Arthur Konovalov).
|
||||
@ -6306,3 +6306,5 @@ Video Disk Recorder Revision History
|
||||
constructor of cReceiver is still available, but it is recommended to plugin authors
|
||||
that they switch to the new interface as soon as possible.
|
||||
When replaying such a recording, the PCR packets are sent to PlayTsVideo()
|
||||
- The files "commands.conf" and "reccmd.conf" can now contain nested lists of
|
||||
commands. See vdr.5 for information about the new file format.
|
||||
|
79
config.c
79
config.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.c 2.9 2010/01/17 15:08:32 kls Exp $
|
||||
* $Id: config.c 2.10 2010/01/31 12:36:36 kls Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@ -22,71 +22,6 @@
|
||||
|
||||
#define ChkDoublePlausibility(Variable, Default) { if (Variable < 0.00001) Variable = Default; }
|
||||
|
||||
// --- cCommand --------------------------------------------------------------
|
||||
|
||||
char *cCommand::result = NULL;
|
||||
|
||||
cCommand::cCommand(void)
|
||||
{
|
||||
title = command = NULL;
|
||||
confirm = false;
|
||||
}
|
||||
|
||||
cCommand::~cCommand()
|
||||
{
|
||||
free(title);
|
||||
free(command);
|
||||
}
|
||||
|
||||
bool cCommand::Parse(const char *s)
|
||||
{
|
||||
const char *p = strchr(s, ':');
|
||||
if (p) {
|
||||
int l = p - s;
|
||||
if (l > 0) {
|
||||
title = MALLOC(char, l + 1);
|
||||
stripspace(strn0cpy(title, s, l + 1));
|
||||
if (!isempty(title)) {
|
||||
int l = strlen(title);
|
||||
if (l > 1 && title[l - 1] == '?') {
|
||||
confirm = true;
|
||||
title[l - 1] = 0;
|
||||
}
|
||||
command = stripspace(strdup(skipspace(p + 1)));
|
||||
return !isempty(command);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *cCommand::Execute(const char *Parameters)
|
||||
{
|
||||
free(result);
|
||||
result = NULL;
|
||||
cString cmdbuf;
|
||||
if (Parameters)
|
||||
cmdbuf = cString::sprintf("%s %s", command, Parameters);
|
||||
const char *cmd = *cmdbuf ? *cmdbuf : command;
|
||||
dsyslog("executing command '%s'", cmd);
|
||||
cPipe p;
|
||||
if (p.Open(cmd, "r")) {
|
||||
int l = 0;
|
||||
int c;
|
||||
while ((c = fgetc(p)) != EOF) {
|
||||
if (l % 20 == 0)
|
||||
result = (char *)realloc(result, l + 21);
|
||||
result[l++] = char(c);
|
||||
}
|
||||
if (result)
|
||||
result[l] = 0;
|
||||
p.Close();
|
||||
}
|
||||
else
|
||||
esyslog("ERROR: can't open pipe for command '%s'", cmd);
|
||||
return result;
|
||||
}
|
||||
|
||||
// --- cSVDRPhost ------------------------------------------------------------
|
||||
|
||||
cSVDRPhost::cSVDRPhost(void)
|
||||
@ -194,7 +129,8 @@ bool cNestedItemList::Parse(FILE *f, cList<cNestedItem> *List, int &Line)
|
||||
*p = 0;
|
||||
s = skipspace(stripspace(s));
|
||||
if (!isempty(s)) {
|
||||
if ((p = strchr(s, '{')) != NULL) {
|
||||
p = s + strlen(s) - 1;
|
||||
if (*p == '{') {
|
||||
*p = 0;
|
||||
stripspace(s);
|
||||
cNestedItem *Item = new cNestedItem(s, true);
|
||||
@ -270,12 +206,11 @@ bool cNestedItemList::Save(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
// --- Folders and Commands --------------------------------------------------
|
||||
|
||||
cNestedItemList Folders;
|
||||
|
||||
// --- cCommands -------------------------------------------------------------
|
||||
|
||||
cCommands Commands;
|
||||
cCommands RecordingCommands;
|
||||
cNestedItemList Commands;
|
||||
cNestedItemList RecordingCommands;
|
||||
|
||||
// --- cSVDRPhosts -----------------------------------------------------------
|
||||
|
||||
|
23
config.h
23
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 2.20 2010/01/17 15:08:32 kls Exp $
|
||||
* $Id: config.h 2.21 2010/01/31 11:14:02 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -48,21 +48,6 @@
|
||||
#define MaxSkinName 16
|
||||
#define MaxThemeName 16
|
||||
|
||||
class cCommand : public cListObject {
|
||||
private:
|
||||
char *title;
|
||||
char *command;
|
||||
bool confirm;
|
||||
static char *result;
|
||||
public:
|
||||
cCommand(void);
|
||||
virtual ~cCommand();
|
||||
bool Parse(const char *s);
|
||||
const char *Title(void) { return title; }
|
||||
bool Confirm(void) { return confirm; }
|
||||
const char *Execute(const char *Parameters = NULL);
|
||||
};
|
||||
|
||||
typedef uint32_t in_addr_t; //XXX from /usr/include/netinet/in.h (apparently this is not defined on systems with glibc < 2.2)
|
||||
|
||||
class cSVDRPhost : public cListObject {
|
||||
@ -187,8 +172,6 @@ public:
|
||||
bool Save(void);
|
||||
};
|
||||
|
||||
class cCommands : public cConfig<cCommand> {};
|
||||
|
||||
class cSVDRPhosts : public cConfig<cSVDRPhost> {
|
||||
public:
|
||||
bool LocalhostOnly(void);
|
||||
@ -196,8 +179,8 @@ public:
|
||||
};
|
||||
|
||||
extern cNestedItemList Folders;
|
||||
extern cCommands Commands;
|
||||
extern cCommands RecordingCommands;
|
||||
extern cNestedItemList Commands;
|
||||
extern cNestedItemList RecordingCommands;
|
||||
extern cSVDRPhosts SVDRPhosts;
|
||||
|
||||
class cSetupLine : public cListObject {
|
||||
|
98
menu.c
98
menu.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.c 2.13 2010/01/29 16:36:57 kls Exp $
|
||||
* $Id: menu.c 2.14 2010/01/31 12:43:24 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -1783,44 +1783,100 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
|
||||
|
||||
class cMenuCommands : public cOsdMenu {
|
||||
private:
|
||||
cCommands *commands;
|
||||
char *parameters;
|
||||
cList<cNestedItem> *commands;
|
||||
cString parameters;
|
||||
cString title;
|
||||
cString command;
|
||||
bool confirm;
|
||||
char *result;
|
||||
bool Parse(const char *s);
|
||||
eOSState Execute(void);
|
||||
public:
|
||||
cMenuCommands(const char *Title, cCommands *Commands, const char *Parameters = NULL);
|
||||
cMenuCommands(const char *Title, cList<cNestedItem> *Commands, const char *Parameters = NULL);
|
||||
virtual ~cMenuCommands();
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
cMenuCommands::cMenuCommands(const char *Title, cCommands *Commands, const char *Parameters)
|
||||
cMenuCommands::cMenuCommands(const char *Title, cList<cNestedItem> *Commands, const char *Parameters)
|
||||
:cOsdMenu(Title)
|
||||
{
|
||||
result = NULL;
|
||||
SetHasHotkeys();
|
||||
commands = Commands;
|
||||
parameters = Parameters ? strdup(Parameters) : NULL;
|
||||
for (cCommand *command = commands->First(); command; command = commands->Next(command))
|
||||
Add(new cOsdItem(hk(command->Title())));
|
||||
parameters = Parameters;
|
||||
for (cNestedItem *Command = commands->First(); Command; Command = commands->Next(Command)) {
|
||||
const char *s = Command->Text();
|
||||
if (Command->SubItems())
|
||||
Add(new cOsdItem(hk(cString::sprintf("%s...", s))));
|
||||
else if (Parse(s))
|
||||
Add(new cOsdItem(hk(title)));
|
||||
}
|
||||
}
|
||||
|
||||
cMenuCommands::~cMenuCommands()
|
||||
{
|
||||
free(parameters);
|
||||
free(result);
|
||||
}
|
||||
|
||||
bool cMenuCommands::Parse(const char *s)
|
||||
{
|
||||
const char *p = strchr(s, ':');
|
||||
if (p) {
|
||||
int l = p - s;
|
||||
if (l > 0) {
|
||||
char t[l + 1];
|
||||
stripspace(strn0cpy(t, s, l + 1));
|
||||
l = strlen(t);
|
||||
if (l > 1 && t[l - 1] == '?') {
|
||||
t[l - 1] = 0;
|
||||
confirm = true;
|
||||
}
|
||||
else
|
||||
confirm = false;
|
||||
title = t;
|
||||
command = skipspace(p + 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
eOSState cMenuCommands::Execute(void)
|
||||
{
|
||||
cCommand *command = commands->Get(Current());
|
||||
if (command) {
|
||||
bool confirmed = true;
|
||||
if (command->Confirm())
|
||||
confirmed = Interface->Confirm(cString::sprintf("%s?", command->Title()));
|
||||
if (confirmed) {
|
||||
Skins.Message(mtStatus, cString::sprintf("%s...", command->Title()));
|
||||
const char *Result = command->Execute(parameters);
|
||||
Skins.Message(mtStatus, NULL);
|
||||
if (Result)
|
||||
return AddSubMenu(new cMenuText(command->Title(), Result, fontFix));
|
||||
return osEnd;
|
||||
cNestedItem *Command = commands->Get(Current());
|
||||
if (Command) {
|
||||
if (Command->SubItems())
|
||||
return AddSubMenu(new cMenuCommands(Title(), Command->SubItems(), parameters));
|
||||
if (Parse(Command->Text())) {
|
||||
if (!confirm || Interface->Confirm(cString::sprintf("%s?", *title))) {
|
||||
Skins.Message(mtStatus, cString::sprintf("%s...", *title));
|
||||
free(result);
|
||||
result = NULL;
|
||||
cString cmdbuf;
|
||||
if (!isempty(parameters))
|
||||
cmdbuf = cString::sprintf("%s %s", *command, *parameters);
|
||||
const char *cmd = *cmdbuf ? *cmdbuf : *command;
|
||||
dsyslog("executing command '%s'", cmd);
|
||||
cPipe p;
|
||||
if (p.Open(cmd, "r")) {
|
||||
int l = 0;
|
||||
int c;
|
||||
while ((c = fgetc(p)) != EOF) {
|
||||
if (l % 20 == 0)
|
||||
result = (char *)realloc(result, l + 21);
|
||||
result[l++] = char(c);
|
||||
}
|
||||
if (result)
|
||||
result[l] = 0;
|
||||
p.Close();
|
||||
}
|
||||
else
|
||||
esyslog("ERROR: can't open pipe for command '%s'", cmd);
|
||||
Skins.Message(mtStatus, NULL);
|
||||
if (result)
|
||||
return AddSubMenu(new cMenuText(title, result, fontFix));
|
||||
return osEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
return osContinue;
|
||||
|
20
vdr.5
20
vdr.5
@ -8,7 +8,7 @@
|
||||
.\" License as specified in the file COPYING that comes with the
|
||||
.\" vdr distribution.
|
||||
.\"
|
||||
.\" $Id: vdr.5 2.12 2010/01/16 15:45:28 kls Exp $
|
||||
.\" $Id: vdr.5 2.13 2010/01/31 12:59:50 kls Exp $
|
||||
.\"
|
||||
.TH vdr 5 "10 Feb 2008" "1.6" "Video Disk Recorder Files"
|
||||
.SH NAME
|
||||
@ -546,6 +546,24 @@ to make sure they are not executed inadvertently.
|
||||
|
||||
Everything following (and including) a '#' character is considered to be comment.
|
||||
|
||||
You can have nested layers of command menus by surrounding a sequence of
|
||||
commands with '{'...'}' and giving it a title, as in
|
||||
|
||||
My Commands {
|
||||
.br
|
||||
First list {
|
||||
Do something: some command
|
||||
Do something else: another command
|
||||
}
|
||||
Second list {
|
||||
Even more: yet another command
|
||||
So much more: and yet another one
|
||||
}
|
||||
.br
|
||||
}
|
||||
|
||||
Command lists can be nested to any depth.
|
||||
|
||||
By default the menu entries in the "Commands" menu will be numbered '1'...'9'
|
||||
to make them selectable by pressing the corresponding number key. If you want
|
||||
to use your own numbering scheme (maybe to skip certain numbers), just precede
|
||||
|
6
vdr.c
6
vdr.c
@ -22,7 +22,7 @@
|
||||
*
|
||||
* The project's page is at http://www.tvdr.de
|
||||
*
|
||||
* $Id: vdr.c 2.15 2010/01/16 15:11:13 kls Exp $
|
||||
* $Id: vdr.c 2.16 2010/01/31 11:14:40 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -582,8 +582,8 @@ int main(int argc, char *argv[])
|
||||
Diseqcs.Load(AddDirectory(ConfigDirectory, "diseqc.conf"), true, Setup.DiSEqC);
|
||||
Channels.Load(AddDirectory(ConfigDirectory, "channels.conf"), false, true);
|
||||
Timers.Load(AddDirectory(ConfigDirectory, "timers.conf"));
|
||||
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"), true);
|
||||
RecordingCommands.Load(AddDirectory(ConfigDirectory, "reccmds.conf"), true);
|
||||
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"));
|
||||
RecordingCommands.Load(AddDirectory(ConfigDirectory, "reccmds.conf"));
|
||||
SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true);
|
||||
Keys.Load(AddDirectory(ConfigDirectory, "remote.conf"));
|
||||
KeyMacros.Load(AddDirectory(ConfigDirectory, "keymacros.conf"), true);
|
||||
|
Loading…
Reference in New Issue
Block a user