Сложная операция getchar () в 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_PAUSE а также ACTION_QUITи я полагаю send_action() просто катит мяч

Вопросы:

Вот что я не понимаю:

  1. Как EOF обнаруживается, когда я даже не нажимаю Войти —> while ((ch[chnum] = getchar()) != EOF) (если вас это смущает, когда воспроизводится фильм, я нажимаю п приостановить фильм, а не п а потом Войти или же Ctrl+D). Я приложил небольшой сценарий ниже с надписью getchar.c который иллюстрирует, как это зацикливается навсегда.
  2. Почему мы в цикле потенциально более 8 итераций в цикле while while ((ch[chnum] = getchar()) != EOF) chnum++ когда массив ch только длины 8?
  3. Это может быть связано с реализацией, но почему массив размером 8, когда все входные данные гарантированно будут иметь длину 1 символ (я могу видеть это здесь на карте и по факту, что ключи обрабатываются мгновенно). Это как-то связано с клавишами со стрелками и клавишей ESC?
  4. Предполагая, что возможно иметь более 1 символа, каким образом эта строка должна делать 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 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;
}

1

Решение

@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 персонаж.

1

Другие решения

Других решений пока нет …