最近,我一直在尝试将命名管道的输出重定向到正在运行的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_PAUSE
和ACTION_QUIT
)进行匹配,并且我认为send_action()
刚好得到了滚动。问题:
这是我不明白的:
while ((ch[chnum] = getchar()) != EOF)
时,如何检测到EOF(如果您对此感到困惑,则在播放电影时,我按p暂停电影,而不是p,然后按Enter或Ctrl + D)。我已在标有getchar.c
的下方附加了一个小脚本,该脚本说明了它如何永远循环。 while ((ch[chnum] = getchar()) != EOF) chnum++
的长度仅为8时,为什么在while循环ch
中循环可能进行8次以上的迭代? if (chnum > 1) ch[0] = ch[chnum - 1] | (ch[chnum - 2] << 8)
吗? 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
字符。