The files "commands.conf" and "reccmd.conf" can now contain nested lists of commands

This commit is contained in:
Klaus Schmidinger 2010-01-31 12:59:50 +01:00
parent 0889960232
commit 86291b6205
6 changed files with 112 additions and 118 deletions

View File

@ -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.

View File

@ -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 -----------------------------------------------------------

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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);