Недавно я пытался перенаправить вывод именованного канала в работающий экземпляр 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_PAUSE
а также ACTION_QUIT
и я полагаю send_action()
просто катит мяч
Вопросы:
Вот что я не понимаю:
while ((ch[chnum] = getchar()) != EOF)
(если вас это смущает, когда воспроизводится фильм, я нажимаю п приостановить фильм, а не п а потом Войти или же Ctrl+D). Я приложил небольшой сценарий ниже с надписью getchar.c
который иллюстрирует, как это зацикливается навсегда.while ((ch[chnum] = getchar()) != EOF) chnum++
когда массив 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
,
Но отправка команд в omxplayer с помощью write () и размер() сообщения вызывает тот же эффект, что и упомянутый выше вопрос. sizeof()
из x_MESSAGE
возвращает 2 в качестве результата, а не 1 (один)! sizeof()
рассчитывает в '\0'-character
(c-кодированной) строки; например "p"
хранится как 'p''\0'
так минимум 2 символа. Так что используйте strlen()
(который нуждается #include <string.h>
) вместо того, как оно будет отправлено только x_MESSAGE
персонаж.
Других решений пока нет …