Mailing List archive

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

[vdr] Dynamic and hierarchical commands.conf menus. (update)



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

With this, you can do things like

* Create a command sub-menu with entries that list the
  sender and subject of each of your mails and show that
  mail when you select the corresponding entry.

* Create a command sub-menu with entries that list the
  currently running processes on your machine and kill
  that process when you select the corresponding entry.

* Create a command sub-menu with entries that list the
  subjects of news sites such as heise.de and list the
  article when you select the corresponding entry.

* Create trees of command sub-menus to browse your 
  directories and start any program in them (or do
  anything else with that file).

* etc., etc.

v-------------------cut along this line-------------------v
*** 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!

You may also want to replace the cOsdMenu::hk method in osd.c
with this new version:

v-------------------cut along this line-------------------v
const char *cOsdMenu::hk(const char *s)
{
  static char buffer[110];
  if (s && hasHotkeys) {
     if (digit == 0 && '1' <= *s && *s <= '9' && *(s + 1) == ' ')
        digit = 11; // prevents automatic hotkeys - input already has them
     if (digit < 10) {
        ++digit;
        snprintf(buffer, sizeof(buffer), " %c %s", digit % 10 + '0', s);
        s = buffer;
        }
     }
  return s;
}
^-------------------cut along this line-------------------^

as I described in another thread.


Now, as a concrete application of the above, I 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 
one 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:

v-------------------cut along this line-------------------v
/*  vdr mail reader.
    Carsten Koch, August 2002.
 */
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define BUF 1024
#define VDR_LINE_LENGTH 100


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+20, VDR_LINE_LENGTH-22);
            found++;
         }
         else if (strncmp(line, "From: ", 6) == 0)
         {
            insert(line+6, from_and_subject, 18);
            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.


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