Отправка нажатий клавиш в подпроцесс, который запускает aplay с использованием fwrite(), pipe() и execlp()

#c #c #linux #alsa

#c #c #linux #alsa

Вопрос:

Я хочу программно воспроизводить произвольные звуки, используя aplay Linux. Помимо воспроизведения я хочу использовать интерактивный режим для приостановки воспроизведения, который может быть достигнут нажатием клавиши пробела при запуске aplay с терминала. Я думаю, этого можно достичь, отправив ' ' через канал процессу, который запускает aplay. Воспроизведение работает, но приостановка — нет.

Как мне ' ' правильно отправить сообщение через канал? Нужно ли мне делать что-то еще?

вот мой код

 #ifndef APLAY_WRAPPER_H
#define APLAY_WRAPPER_H

#include <sys/types.h>

#include <csignal>
#include <iostream>
#include <stdio.h>
#include <string>
#include <unistd.h>

class APlayWrapper
{
private:
  pid_t m_pid;
  int pipefd[2];  // [0] is for reading and [1] is for writing
  FILE* m_sub_process_input;

public:
  APlayWrapper() : m_pid(0){};

  ~APlayWrapper(){};

  void play(const std::stringamp; pathToFile)
  {
    pipe(pipefd);    // create a pipe
    m_pid = fork();  // spawn a child process
    if (m_pid == 0)
    {
      execlp("/usr/bin/aplay", "/usr/bin/aplay", "-i", pathToFile, (char*)NULL);
    }

    m_sub_process_input = fdopen(pipefd[1], "w");
  };

  void stopPlayback()
  {
    if (isPlaying())
    {
      kill(m_pid, SIGTERM);
    }
  };

  void pauseResumePlayback()
  {
    fwrite(" ", sizeof(char), 1, m_sub_process_input);
  };

  bool isPlaying()
  {
    if (0 == kill(m_pid, 0))
    {
      return true;
    }
    return false;
  }
};

#endif
  

Комментарии:

1. Вероятно, вам нужно перевести m_sub_process_input поток в небуферизованный режим. Но использование потока кажется излишним. Вы могли бы просто использовать POSIX более низкого уровня write() в файловом дескрипторе. Кроме того, в дочернем элементе вам необходимо dup2() прочитать конец канала до стандартного дескриптора входного файла перед exec .

2. Вы не можете отправлять «нажатия клавиш» через канал. Канал предназначен для отправки данных. Если вы хотите взаимодействовать с программой, которая использует терминал для «интерактивных» действий, вам следует использовать pty вместо канала. Если вы просто выполняете быстрый взлом, вы можете заставить свой образец работать, вызвав fflush after fwrite , но это будет ненадежно, поскольку это будет зависеть от того, как именно aplay считывает данные с терминала.

3. aplay фактически считывает из stdin .