diff options
-rw-r--r-- | HISTORY | 4 | ||||
-rw-r--r-- | config.c | 79 | ||||
-rw-r--r-- | config.h | 23 | ||||
-rw-r--r-- | menu.c | 98 | ||||
-rw-r--r-- | vdr.5 | 20 | ||||
-rw-r--r-- | vdr.c | 6 |
6 files changed, 112 insertions, 118 deletions
@@ -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. @@ -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; } -cNestedItemList Folders; - -// --- cCommands ------------------------------------------------------------- +// --- Folders and Commands -------------------------------------------------- -cCommands Commands; -cCommands RecordingCommands; +cNestedItemList Folders; +cNestedItemList Commands; +cNestedItemList RecordingCommands; // --- cSVDRPhosts ----------------------------------------------------------- @@ -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 { @@ -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; @@ -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 @@ -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); |