最近,我一直在尝试将命名管道的输出重定向到正在运行的omxplayer实例(请参阅here以获取即使它应该控制omxplayer的最小工作示例)。我怀疑它与读取和写入管道有关-也许追加了新行-因此我得到了一些帮助,并编写了一个C程序,该程序写入并读取管道(请参阅here),但事实证明也不是读/写错误。因此,我去追踪了omxplayer的代码,以为不管它多么复杂,最终都必须有一个地方,那里有读取用户输入的标准C++代码,谢天谢地,我找到了它。据我所知,这是一种方法,负责获取用户输入并为Dbus做好一切准备工作:

void Keyboard::Process()
{
  while(!m_bStop && conn && dbus_connection_read_write_dispatch(conn, 0))
  {
    int ch[8];
    int chnum = 0;

    while ((ch[chnum] = getchar()) != EOF) chnum++;

    if (chnum > 1) ch[0] = ch[chnum - 1] | (ch[chnum - 2] << 8);

    if (m_keymap[ch[0]] != 0)
          send_action(m_keymap[ch[0]]);
    else
      Sleep(20);
  }
}

据我所知,while(!m_bStop...是有条件的,只是为了确保一切正常,m_keymap是一种密码,它将诸如'p''q'之类的整数与枚举值(例如ACTION_PAUSEACTION_QUIT)进行匹配,并且我认为send_action()刚好得到了滚动。

问题:

这是我不明白的:
  • 当我什至不按Enter-> while ((ch[chnum] = getchar()) != EOF)时,如何检测到EOF(如果您对此感到困惑,则在播放电影时,我按p暂停电影,而不是p,然后按Enter或Ctrl + D)。我已在标有getchar.c的下方附加了一个小脚本,该脚本说明了它如何永远循环。
  • 当数组while ((ch[chnum] = getchar()) != EOF) chnum++的长度仅为8时,为什么在while循环ch中循环可能进行8次以上的迭代?
  • 这可能是特定于实现的,但是为什么在保证所有输入都为1个字符长的情况下使用大小为8的数组(我可以在 map 上看到它,并且可以立即处理键的事实)。这与箭头键和转义键有什么关系吗?
  • 假设可能有多个字符,以某种方式,此行应该执行if (chnum > 1) ch[0] = ch[chnum - 1] | (ch[chnum - 2] << 8)吗?
  • 最后,知道omxplayer如何读取用户生成的输入,谁能告诉我为什么我的标为omxplayer_test.c的简单脚本无法成功控制播放器?

  • getchar.c:
    #include <stdio.h>
    
    int main( int argc, char *argv[] ) {
       int ch [ 8 ];
       int chnum = 0;
    
    
       while ( ( ch [ chnum ] = getchar() ) != EOF ) chnum++;
       printf ( "You will never make it here!\n" );
    
       return 0;
    }
    

    omxplayer_test.c:
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    #include <stdbool.h>
    
    #define PIPE_PATH "testpipe"
    #define VIDEO_PATH "Matrix.mkv"
    #define P_MESSAGE "p"
    #define Q_MESSAGE "q"
    #define I_MESSAGE "."
    #define VIDEO_PLAYER "omxplayer"
    #define SLEEP_PERIOD 2L
    
    int main()
    {
       int fd;
       pid_t pid;
       pid_t wpid;
       int status;
       char shellCmd [ 1000 ];
       struct timespec time1, time2; //used for sleeping
       bool parent;
       char c;
    
       parent = false;
    
       //Make pipe BEFORE forking
       mkfifo ( PIPE_PATH, 0666 );
    
       if ( ( pid = fork () ) < 0 )
       {
          perror ( "Fork Failed\n" );
          return -1;
       }
       else if ( pid == 0 )
       { //first child launches the movie
          sprintf ( shellCmd,  "%s %s < %s >/dev/null 2>&1", VIDEO_PLAYER,  VIDEO_PATH, PIPE_PATH );
          if ( system ( shellCmd ) == -1 )
          {
             printf ( "Error: %s\n", shellCmd );
             fflush(stdout);
          }
          printf ("First child finished\n");
          fflush (stdout);
       }
       else
       {
          if ( ( pid = fork () ) < 0 )
          {
             perror ( "Fork Failed\n" );
             return -1;
          }
          else if ( pid == 0 )
          { //second child waits x seconds then pauses/unpauses/quits movie
             time1.tv_sec = SLEEP_PERIOD; //sleep for x seconds
             time1.tv_nsec = 0L; //Dont worry about milli seconds
    
             nanosleep ( &time1, &time2 );
    
             //Suprisingly, this signal which gets ball rolling works
             fd = open ( PIPE_PATH, O_WRONLY );
             write ( fd, I_MESSAGE, sizeof ( I_MESSAGE ) );
    
             nanosleep ( &time1, &time2 );
    
             printf ( "Sleep over, pausing movie\n");
             fflush(stdout);
    
             write ( fd, I_MESSAGE, sizeof ( P_MESSAGE ) );
    
             nanosleep ( &time1, &time2 );
    
             printf ( "Sleep over, unpausing movie\n");
             fflush(stdout);
    
             write ( fd, P_MESSAGE, sizeof ( P_MESSAGE ) );
    
             nanosleep ( &time1, &time2 );
    
             printf ( "Sleep over, quiting movie\n");
             fflush(stdout);
    
             write ( fd, Q_MESSAGE, sizeof ( Q_MESSAGE ) );
             close ( fd );
    
             printf ("Second child finished\n");
             fflush (stdout);
          }
          else
          {
             parent = true;
          }
       }
    
       while ( ( wpid = wait ( &status ) ) > 0 )
       {
          printf ( "Exit status of %d was %d (%s)\n", ( int ) wpid, status, ( status == 0 ) ? "accept" : "reject" );
          fflush(stdout);
       }
    
       if ( parent == true )
       {
          printf ("deleting pipe\n");
          fflush(stdout);
          unlink ( PIPE_PATH );
       }
    
       return 0;
    }
    

    最佳答案

    @puk我偶然发现了您的“旧”问题,但如果您自己没有回答,请以我为准。

    看看https://github.com/popcornmix/omxplayer/issues/131上类似的内容。当omxplayer发布的0.3.x版本来自此popcornmix存储库时,我将在此处回答这些问题,因为它是您解决omxplayer问题的好地方;)

    但是我会回答一个问题,为什么您的omxplayer_test.c在这里不起作用,因为是让您的omxplayer失败的代码:)完全不正确,因为这是omxplayer中的当前问题:(

    I_MESSAGE的发送给我最大的惊喜,因为我不知道对'。'的任何键盘输入处理。字符。另一方面,“i”命令omxplayer转到上一章。因此,如果您未在'。'上进行任何键映射。输入键或表示真正的“i”操作,只需将其省略即可;它不是(也不应该)启动omxplayer

    要暂停omxplayer,您可以使用I_MESSAGE(而不是P_MESSAGE)输入错误。

    但是,使用消息的write()和 sizeof()向omxplayer发送命令会产生与上述问题相同的效果。 sizeof()x_MESSAGE返回2作为结果,而不是1(一个)! sizeof()计入(c编码)字符串的'\0'-character中;例如"p"存储为'p''\0',因此至少2个字符。因此,请改为使用 strlen() (需要#include <string.h>),因为它将仅发送x_MESSAGE字符。

    09-04 02:38