표준 입력의 키보드 명령을 통해 볼륨 제어와 같은 유용한 작업을 수행할 수 있는 대화형 모드가 있는 mpg123 프로그램이 있습니다. mpg123을 시작하여 명명된 파이프에서 명령을 읽으려고 합니다. 이렇게 하면 다른 프로그램과 상호 작용할 수 있습니다.
터미널에서는 다음을 수행합니다.
mkfifo pipe
tail -n1 -f pipe | mpg123 -vC /some/song.mp3
다른 터미널에서는 다음을 수행합니다.
cat > pipe
-
-
이제 나는 터미널에 앉아 키를 누르는 것처럼 이것이 mpg123 프로그램으로 전송되기를 기대하고 있지만 -, 그렇지 않습니다. 누구든지 내가 뭘 잘못하고 있는지 말해 줄 수 있나요?
답변1
-C
이로 인해 mpg123이 표준 입력이 아닌 터미널에서 읽혀지는 것 같습니다 . 그러나 내 mpg123 매뉴얼 페이지 버전에서는 다음과 같은 내용을 볼 수 있습니다.
-R, --remote
Activate generic control interface. mpg123 will then read and
execute commands from stdin. Basic usage is ``load <filename> ''
to play some file and the obvious ``pause'', ``command. ``jump
<frame>'' will jump/seek to a given point (MPEG frame number).
Issue ``help'' to get a full list of commands and syntax.
이것이 당신이 찾고 있는 것일 수도 있습니다 mpg123 -vR <pipe
. 예시의 상호 작용은 다음과 같습니다(볼륨이 30%로 설정됨).
$ cat >pipe
load /some/song.mp3
volume 30
그러나 이로 인해 터미널 대신 명명된 파이프에 연결될 때 이전 모드가 stdin에서 데이터를 읽는 데 실패하게 됩니까 -C
?-R
mpg123 소스 코드를 간단히 살펴보면 터미널에서 키 입력을 읽기 위해 termios 도구를 사용한다는 것을 알 수 있습니다. 이
tcsetattr
도구는 키 입력이 추가 처리 없이 판독기로 전송되는 소위 "비정규 모드"로 전환하는 데 사용됩니다. (특히, 전체 줄이 입력될 때까지 기다릴 필요가 없습니다):
struct termios tio = *pattern;
(...)
tio.c_lflag &= ~(ICANON|ECHO);
(...)
return tcsetattr(0,TCSANOW,&tio);
(이것은 다음과 같다.GNU libc 코드 예제.)
그런 다음 루프에서 파일 설명자 0(stdin)에 사용 가능한 데이터가 있는지 확인하고, 그렇다면 해당 데이터에서 바이트를 읽는 get_key
함수가 호출됩니다 ( ). 그러나 터미널은 작동하지만 파이프는 작동하지 않는 이유를 여전히 설명하지 못합니다! 대답은 터미널 초기화 코드에 있습니다.select
read(0,val,1)
/* initialze terminal */
void term_init(void)
{
debug("term_init");
term_enable = 0;
if(tcgetattr(0,&old_tio) < 0)
{
fprintf(stderr,"Can't get terminal attributes\n");
return;
}
if(term_setup(&old_tio) < 0)
{
fprintf(stderr,"Can't set terminal attributes\n");
return;
}
term_enable = 1;
}
tcgetattr
실패 하거나 term_setup
실패 하면 0 으로 term_enable
설정됩니다 . (터미널에서 키 누르기를 읽는 함수는 로 시작합니다 if(!term_enable) return 0;
.) 실제로 stdin이 터미널이 아닌 경우
tcgetattr
실패가 발생하고 해당 오류 메시지가 인쇄되며 키 누르기 처리 코드는 건너뜁니다.
$ mpg123 -C ~/input.mp3 <pipe
(...)
Can't get terminal attributes
이는 파이프를 통해 명령을 보내려는 시도가 mpg123 -C
실패하는 이유를 설명합니다. 이는 구현자에게 논란의 여지가 있는 선택입니다. 아마도 키 입력 처리 코드 처리를 비활성화하는 대신 단순히 허용 tcgetattr
/ tcsetattr
실패(아마도 이 목적으로 스위치를 사용하여)하면 성공할 것입니다.