Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[vdr] Dynamic and hierarchical commands.conf menus.



Here is a four line patch that allows you to create
dynamic and hierarchical commands.conf menus:

--------------------cut along this line--------------------
*** vdr-1.0.4+aio/menu.c    Sat Aug 31 03:08:31 2002
--- /home/cko/vdr-1.0.4+aio/menu.c      Sat Aug 31 02:23:19 2002
***************
*** 3129,3134 ****
--- 3129,3138 ----
       const char *Result = command->Execute();
       if (Result)
          return AddSubMenu(new cMenuText(command->Title(), Result, fontFix));
+      else {
+         Commands.Load("commands.conf");
+         return osCommands;
+         }
       }
    return osContinue;
  }
--------------------cut along this line--------------------


This patch is a bit crude, since it reloads commands.conf from the
current working directory. I was too lazy to figure out how to get
at ConfigDirectory from within cMenuCommands::Execute. Since I use
the current working directory for my config files anyway, it does
not matter to me.

What this patch does: If the command executed does not return any
output, commands.conf is reloaded.
This allows you to write shell commands that redefine the commands 
menu!

As an example, I now have a main commands menu that has all my
regular commands and a command "Mail", which redefines the commands
menu to a menu that contains a menu item for each of my mails.
Of course, that secondary commands menu also has an entry that
restores my main commands menu.

How is this done?
My main commands menu is on commands_main.conf.
Initially, there is a symbolic link from commands_main.conf to 
commands.conf, so vdr initially reads commands_main.conf and
displays it. 

The "Mail" entry on commands_main.conf looks like this:

Mail:/home/cko/bin/list_mail < /wald/var/mail/cko > commands_mail.conf;rm -f commands.conf;ln -s commands_mail.conf commands.conf

so it runs the list_mail program without parameters, which
creates/updates commands_mail.conf and creates a new link
which now links commands_mail.conf to commands.conf.
My tiny patch makes sure that this new commands.conf is
re-read after executing the "Mail" entry.
A sample output of list_mail looks like this:

Main commands:rm -f commands.conf;ln -s commands_main.conf commands.conf
Carsten Koch <cko>   Test.:/home/cko/bin/list_mail 1 </wald/var/mail/cko
Carsten Koch <cko>   da|ad:/home/cko/bin/list_mail 2 </wald/var/mail/cko

As you see, the first entry restores the main commands and the other
entries show my individual mails, where the command name is derived
from the From: and Subject: headers.

Here is the list_mail program:


/*  vdr mail reader.
    Carsten Koch, August 2002.
 */
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define BUF 1024
#define VDR_LINE_LENGTH 53


static void insert(const char * what, char * where, const int limit)

{
   int length = 0;
   while (isprint(*what) && (length++ < limit))
   {
      const char ch = *what++;
      *where++ = ch == ':'? '|' : ch;
   }
}   
            

   

static void make_command_entries()

{
   char line[BUF+1];
   int mails = 0;
   
   printf("Main commands:rm -f commands.conf;ln -s commands_main.conf commands.conf\n");
   
   fgets(line, BUF, stdin);
   for (;;)
   {
      int found = 0;
      char from_and_subject[VDR_LINE_LENGTH+1];
      while ((!feof(stdin)) && (strncmp(line, "From ", 5) != 0))
         fgets(line, BUF, stdin);
      if (feof(stdin)) break;
      mails++;
      strcpy(from_and_subject, "                      ");
      do
      {
         fgets(line, BUF, stdin);
         if (strncmp(line, "Subject: ", 9) == 0)
         {
            insert(line+9, from_and_subject+21, VDR_LINE_LENGTH-22);
            found++;
         }
         else if (strncmp(line, "From: ", 6) == 0)
         {
            insert(line+6, from_and_subject, 20);
            found++;
         }
      } while (! ((found == 2) || feof(stdin) || 
                  (strncmp(line, "From ", 5) == 0)));
      printf("%s:/home/cko/bin/list_mail %d </wald/var/mail/cko\n", from_and_subject, mails);
   }
}


static void list_message(const int msgnr)

{
   char line[BUF+1];
   int mail = 0;

   do
   {
      fgets(line, BUF, stdin);
      while ((!feof(stdin)) && (strncmp(line, "From ", 5) != 0))
         fgets(line, BUF, stdin);
      if (feof(stdin)) return;
      mail++;
   } while (mail != msgnr);
   do
   {
      fgets(line, BUF, stdin);
      if (feof(stdin) || (strncmp(line, "From ", 5) == 0))
         return;
   } while (line[0] != '\n');
   do
   {
      printf("%s", line);
      fgets(line, BUF, stdin);
   } while (! (feof(stdin) || (strncmp(line, "From ", 5) == 0)));
}


main(int argc, char **argv)

{
   if (argc == 1)
      make_command_entries();
   else
      list_message(atoi(argv[1]));
}
--------------------cut along this line--------------------


I hope that this will be as useful to some of you as it is to me.
Use at your own risk, etc. Standard disclaimers apply.


Here are a few ideas for additional uses:

You could define a "Kill" entry that creates "ps" output as 
the command name and a kill command for each corresponding 
process number.

You could define a "Browse" entry that creates "ls" output as 
the command name and another ls command for directory entries.

The mail thing could be extended so it can also delete mails.

You could define a "Lynx" entry that shows a text-based internet
page (such as heise.de) with the article headlines as the command
names and further commands that show the article text.

etc., etc.

Please let me know what you think: good idea? bad idea?

If you create any interesting command entries, 
please post them on the list!


Carsten.




Home | Main Index | Thread Index