omxplayer中复杂的getchar()操作

Complex getchar() operation in omxplayer

本文关键字:操作 getchar 复杂 omxplayer      更新时间:2023-10-16

最近我一直在尝试将命名管道的输出重定向到omxplayer的运行实例中(请参阅此处以获取一个不控制omxplayer的最低工作示例,尽管它应该控制omxplayer)。我怀疑这与对管道的读写有关——也许附加了一行新行——所以我得到了一些帮助,编写了一个C程序,它向管道写入并从中读取(见此处),但事实证明这也不是读/写错误。因此,我去追踪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()只是开始了。

问题:

以下是我不明白的:

  1. 当我甚至没有按Enter-->while ((ch[chnum] = getchar()) != EOF)时,EOF是如何检测到的(如果您对此感到困惑,当播放电影时,我会按p暂停电影,而不是p,然后按下EnterCtrl+1D
  2. 当数组ch的长度只有8时,为什么我们在while循环while ((ch[chnum] = getchar()) != EOF) chnum++中循环可能超过8次迭代
  3. 这可能是特定于实现的,但为什么当所有输入都保证为1个字符长时,大小为8的数组(我可以在映射中看到它,而且键是即时处理的)。这与箭头键和逃生键有任何关系吗
  4. 假设可能有一个以上的字符,不知何故,这行应该做什么if (chnum > 1) ch[0] = ch[chnum - 1] | (ch[chnum - 2] << 8)
  5. 最后,知道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 Failedn" );
      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: %sn", shellCmd );
         fflush(stdout);
      }
      printf ("First child finishedn");
      fflush (stdout);
   }
   else
   {
      if ( ( pid = fork () ) < 0 )
      {
         perror ( "Fork Failedn" );
         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 movien");
         fflush(stdout);
         write ( fd, I_MESSAGE, sizeof ( P_MESSAGE ) );
         nanosleep ( &time1, &time2 );
         printf ( "Sleep over, unpausing movien");
         fflush(stdout);
         write ( fd, P_MESSAGE, sizeof ( P_MESSAGE ) );
         nanosleep ( &time1, &time2 );
         printf ( "Sleep over, quiting movien");
         fflush(stdout);
         write ( fd, Q_MESSAGE, sizeof ( Q_MESSAGE ) );
         close ( fd );
         printf ("Second child finishedn");
         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 pipen");
      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"操作,只需忽略它;不需要(也不应该)启动CCD_ 20。

要暂停omxplayer,您输入的是I_MESSAGE而不是P_MESSAGE

但是,使用write()和消息的sizeof()向omxplayer发送命令会产生与前面提到的问题相同的效果。x_MESSAGEsizeof()返回2作为结果,而不是1(一)!CCD_ 26在(c编码的)串的CCD_ 27中计数;例如"p"被存储为'p''',因此至少有2个字符。因此,请使用strlen()(需要#include <string.h>),因为它只发送x_MESSAGE字符。