Forum général.cherche-logiciel Lancer une commande lors de l'appui sur une touche du clavier

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
3
25
nov.
2022

Bonjour à tous,

Je cherche un petit logiciel qui permet d'écouter les événements en provenance du clavier et de lancer une commande en fonction de la touche pressée.

Le contexte est le suivant : je possède une télécommande OSMC branchée en USB sur un Raspberry Pi 3, cette télécommande est vue comme un clavier par l'OS (avec les entrées qui vont bien dans /dev/input/). Et je souhaite utiliser cette télécommande pour piloter un MPD installé sur ce même Raspberry Pi 3.

Pour le moment, je m'en sors avec inputlirc et irexec. inputlirc va lire les événements du clavier et envoyer des infos dans un socket Unix, et irexec écoute sur ce même socket Unix et lance des commandes en fonction de la touche du clavier.
Ça fonctionne, mais je cherche un truc plus simple :
* qui fait le job à la fois de inputlirc et irexec (un seul démon au lieu de deux)
* qui n'embarque pas les 200Mo de dépendance de lirc

Merci :)

  • # sxhkd ?

    Posté par  (site web personnel) . Évalué à 4.

    sxhkd fait partie du gestionnaire de fenêtre bspwm. C’est un petit démon utilisé dans le gestionnaire pour gérer tous les raccourcis claviers mais peut être utilisé de manière autonome. Il est paramétré avec un simple fichier texte (et un syntaxe très concise)

    • [^] # Re: sxhkd ?

      Posté par  . Évalué à 1.

      Merci pour la proposition, mais j'ai oublié de précisé que le Raspberry Pi est en headless : pas de clavier/souris (hormis la télécommande OSMC), ni d'écran et encore moins de Xorg ou Wayland. Et sxhkd semble être pensé pour s'exécuter dans un environnement X.

      pi@raspberrypi:~ $ sxhkd 
      Can't open display.
      
  • # Côté Xorg…

    Posté par  . Évalué à 1.

    Essaie de regarder si ton gestionnaire de fenêtre/bureau (kde, gnome, etc.) ne propose pas un tel utilitaire ou option de configuration.

    Mort aux cons !

    • [^] # Re: Côté Xorg…

      Posté par  . Évalué à 1.

      Comme indiqué dans la réponse au commentaire de chimrod, il n'y a aucun gestionnaire de fenêtre/bureau d'installé sur le Raspberry Pi. Au mieux, il y a toujours le framebuffer, mais si je peux éviter d'installer tout un environnement de bureau pour juste lire les /dev/input/event* et lancer des commandes, ça m'arrangerait :)

      • [^] # Re: Côté Xorg…

        Posté par  . Évalué à 1.

        Tu sais coder un peu ?

        Mort aux cons !

        • [^] # Re: Côté Xorg…

          Posté par  . Évalué à 2. Dernière modification le 25/11/22 à 13:05.

          #include <fcntl.h>
          #include <stdio.h>
          #include <sys/time.h>
          #include <unistd.h>
          
          /* config, avec un qwerty en exemple */
          struct config {
                  int key; char **cmd;
                  };
          
          static char *echo_q[] = { "echo", "touche q active", NULL };
          static char *echo_w[] = { "echo", "touche", "w", "active", NULL };
          
          static struct config myconf[] = {
                  /* { key code, cmd } */
                  {16, echo_q},
                  {17, echo_w},
                  };
          
          int main (int argc, char *argv[])
          {
                  int kbd, i;
                  struct {
                          struct timeval time;
                          unsigned short type;
                          unsigned short code;
                          unsigned int value;
                          } ev;
                  if (argc != 2)
                          return 2;
                  kbd = open (argv[1], O_RDONLY);
                  if (kbd < 0)
                          return 1;
                  loop_forever:
                          read (kbd, &ev, sizeof(ev));
                          if (1 == ev.type && 1 == ev.value) {
                                  for (i = 0; i < sizeof (myconf) / sizeof (struct config); i++)
                                          if (myconf[i].key == ev.code) {
                                                  if (0 == fork ())
                                                          execvp (myconf[i].cmd[0], myconf[i].cmd);
                                                  goto loop_forever;
                                          }
                                  /* pour avoir le codekey, sinon commenter: */
                                  printf ("%d:%d:%d\n", ev.type, ev.code, ev.value);
                          }
                          goto loop_forever;
          }

          Enregistrer le code dans un fichier inex.c, modifier le myconf comme souhaité, puis un simple :

          gcc inex.c -o inex
          ./inex /dev/inputN

          C-c ou kill pour arrêter le programme.

          Edit : j’ai oublié la récolte des codes retour des fils, je corrigerai d’ici ce soir… sauf si un autre contributeur s’en charge.

          Mort aux cons !

          • [^] # Re: Côté Xorg…

            Posté par  . Évalué à 3.

            Voici le code sans zombies :

            #include <fcntl.h>
            #include <stdio.h>
            #include <sys/time.h>
            #include <sys/wait.h>
            #include <unistd.h>
            
            /* config, avec un qwerty en exemple */
            struct config {
                    int key; char **cmd;
                    };
            
            static char *echo_q[] = { "echo", "touche q active", NULL };
            static char *echo_w[] = { "echo", "touche", "w", "active", NULL };
            static char *sleep_9[] = { "sleep", "9", NULL };
            
            static struct config myconf[] = {
                    /* { key code, cmd } */
                    {16, echo_q},
                    {17, echo_w},
                    {18, sleep_9},
                    };
            
            int main (int argc, char *argv[])
            {
                    int kbd, pid;
                    struct config *p;
                    struct {
                            struct timeval time;
                            unsigned short type;
                            unsigned short code;
                            unsigned int value;
                            } ev;
                    if (argc != 2)
                            return 2;
                    kbd = open (argv[1], O_RDONLY);
                    if (kbd < 0)
                            return 1;
                    loop_forever:
                            read (kbd, &ev, sizeof(ev));
                            if (1 == ev.type && 1 == ev.value) {
                                    for (p = myconf; p < myconf + sizeof (myconf) / sizeof (struct config); p++)
                                            if (p->key == ev.code) {
                                                    pid = fork ();
                                                    if (0 == pid) {
                                                            if (0 == fork ())
                                                                    /* execlp pour exclure la recherche dans $PATH */
                                                                    execvp (p->cmd[0], p->cmd);
                                                            return 0;
                                                    } else {
                                                            if (pid > 0)
                                                                    waitpid (pid, NULL, 0);
                                                    }
                                                    goto loop_forever;
                                            }
                                    /* pour avoir le codekey, sinon commenter: */
                                    printf ("%d:%d:%d\n", ev.type, ev.code, ev.value);
                            }
                            goto loop_forever;
            }

            Mort aux cons !

            • [^] # Re: Côté Xorg…

              Posté par  . Évalué à 2.

              Merci ! Mon C est un peu rouillé mais je vois comment ça fonctionne.
              Je pensais honnêtement qu'un programme similaire au tien existait déjà et était packagé dans debian/raspbian (mais non en fait).

              Encore merci pour ton aide :)

  • # Bash

    Posté par  (site web personnel) . Évalué à 7.

    J'avais exactement le même besoin, j'ai bricolé un script bash pour ça: https://blog.lkiefer.org/index.php?article3/script-pour-mpd

    Un LUG en Lorraine : https://enunclic-cappel.fr

    • [^] # Re: Bash

      Posté par  . Évalué à 1.

      Super intéressant de faire pour tourner le programme sur tty1. Je n'y avais pas pensé.
      Est-ce que le user qui lance numpd.sh à besoin de permissions particulières ? (comme être dans le groupe input par exemple)

      • [^] # Re: Bash

        Posté par  (site web personnel) . Évalué à 2.

        Je ne pense pas, je crois que j'avais crée un user "mpd" et laissé le paramétrage par défaut. Mais ça fait déjà 10 ans, tu me confirmeras ça ;)

        Un LUG en Lorraine : https://enunclic-cappel.fr

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.