1
0
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:
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 - Fixed plugin arguments corruption with glibc 2.11 on x86_64 (thanks to
Anssi Hannula). 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". - Changed the EVCONTENTMASK_* macros to enums and changed "mask" to "group".
- Updated the Estonian OSD texts (thanks to Arthur Konovalov). - 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 constructor of cReceiver is still available, but it is recommended to plugin authors
that they switch to the new interface as soon as possible. that they switch to the new interface as soon as possible.
When replaying such a recording, the PCR packets are sent to PlayTsVideo() 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 * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "config.h"
@ -22,71 +22,6 @@
#define ChkDoublePlausibility(Variable, Default) { if (Variable < 0.00001) Variable = Default; } #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::cSVDRPhost(void) cSVDRPhost::cSVDRPhost(void)
@ -194,7 +129,8 @@ bool cNestedItemList::Parse(FILE *f, cList<cNestedItem> *List, int &Line)
*p = 0; *p = 0;
s = skipspace(stripspace(s)); s = skipspace(stripspace(s));
if (!isempty(s)) { if (!isempty(s)) {
if ((p = strchr(s, '{')) != NULL) { p = s + strlen(s) - 1;
if (*p == '{') {
*p = 0; *p = 0;
stripspace(s); stripspace(s);
cNestedItem *Item = new cNestedItem(s, true); cNestedItem *Item = new cNestedItem(s, true);
@ -270,12 +206,11 @@ bool cNestedItemList::Save(void)
return result; return result;
} }
// --- Folders and Commands --------------------------------------------------
cNestedItemList Folders; cNestedItemList Folders;
cNestedItemList Commands;
// --- cCommands ------------------------------------------------------------- cNestedItemList RecordingCommands;
cCommands Commands;
cCommands RecordingCommands;
// --- cSVDRPhosts ----------------------------------------------------------- // --- cSVDRPhosts -----------------------------------------------------------

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __CONFIG_H
@ -48,21 +48,6 @@
#define MaxSkinName 16 #define MaxSkinName 16
#define MaxThemeName 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) 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 { class cSVDRPhost : public cListObject {
@ -187,8 +172,6 @@ public:
bool Save(void); bool Save(void);
}; };
class cCommands : public cConfig<cCommand> {};
class cSVDRPhosts : public cConfig<cSVDRPhost> { class cSVDRPhosts : public cConfig<cSVDRPhost> {
public: public:
bool LocalhostOnly(void); bool LocalhostOnly(void);
@ -196,8 +179,8 @@ public:
}; };
extern cNestedItemList Folders; extern cNestedItemList Folders;
extern cCommands Commands; extern cNestedItemList Commands;
extern cCommands RecordingCommands; extern cNestedItemList RecordingCommands;
extern cSVDRPhosts SVDRPhosts; extern cSVDRPhosts SVDRPhosts;
class cSetupLine : public cListObject { class cSetupLine : public cListObject {

94
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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" #include "menu.h"
@ -1783,46 +1783,102 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
class cMenuCommands : public cOsdMenu { class cMenuCommands : public cOsdMenu {
private: private:
cCommands *commands; cList<cNestedItem> *commands;
char *parameters; cString parameters;
cString title;
cString command;
bool confirm;
char *result;
bool Parse(const char *s);
eOSState Execute(void); eOSState Execute(void);
public: 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 ~cMenuCommands();
virtual eOSState ProcessKey(eKeys Key); 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) :cOsdMenu(Title)
{ {
result = NULL;
SetHasHotkeys(); SetHasHotkeys();
commands = Commands; commands = Commands;
parameters = Parameters ? strdup(Parameters) : NULL; parameters = Parameters;
for (cCommand *command = commands->First(); command; command = commands->Next(command)) for (cNestedItem *Command = commands->First(); Command; Command = commands->Next(Command)) {
Add(new cOsdItem(hk(command->Title()))); 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() 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) eOSState cMenuCommands::Execute(void)
{ {
cCommand *command = commands->Get(Current()); cNestedItem *Command = commands->Get(Current());
if (command) { if (Command) {
bool confirmed = true; if (Command->SubItems())
if (command->Confirm()) return AddSubMenu(new cMenuCommands(Title(), Command->SubItems(), parameters));
confirmed = Interface->Confirm(cString::sprintf("%s?", command->Title())); if (Parse(Command->Text())) {
if (confirmed) { if (!confirm || Interface->Confirm(cString::sprintf("%s?", *title))) {
Skins.Message(mtStatus, cString::sprintf("%s...", command->Title())); Skins.Message(mtStatus, cString::sprintf("%s...", *title));
const char *Result = command->Execute(parameters); 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); Skins.Message(mtStatus, NULL);
if (Result) if (result)
return AddSubMenu(new cMenuText(command->Title(), Result, fontFix)); return AddSubMenu(new cMenuText(title, result, fontFix));
return osEnd; return osEnd;
} }
} }
}
return osContinue; return osContinue;
} }

20
vdr.5
View File

@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the .\" License as specified in the file COPYING that comes with the
.\" vdr distribution. .\" 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" .TH vdr 5 "10 Feb 2008" "1.6" "Video Disk Recorder Files"
.SH NAME .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. 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' 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 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 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 * 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> #include <getopt.h>
@ -582,8 +582,8 @@ int main(int argc, char *argv[])
Diseqcs.Load(AddDirectory(ConfigDirectory, "diseqc.conf"), true, Setup.DiSEqC); Diseqcs.Load(AddDirectory(ConfigDirectory, "diseqc.conf"), true, Setup.DiSEqC);
Channels.Load(AddDirectory(ConfigDirectory, "channels.conf"), false, true); Channels.Load(AddDirectory(ConfigDirectory, "channels.conf"), false, true);
Timers.Load(AddDirectory(ConfigDirectory, "timers.conf")); Timers.Load(AddDirectory(ConfigDirectory, "timers.conf"));
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"), true); Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"));
RecordingCommands.Load(AddDirectory(ConfigDirectory, "reccmds.conf"), true); RecordingCommands.Load(AddDirectory(ConfigDirectory, "reccmds.conf"));
SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true); SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true);
Keys.Load(AddDirectory(ConfigDirectory, "remote.conf")); Keys.Load(AddDirectory(ConfigDirectory, "remote.conf"));
KeyMacros.Load(AddDirectory(ConfigDirectory, "keymacros.conf"), true); KeyMacros.Load(AddDirectory(ConfigDirectory, "keymacros.conf"), true);