
Я пытаюсь написать программу, которая поможет читать текстовые и PDF-документы на языке C, используя программы с открытым исходным кодом на Raspberry Pi.
программа простая, ничего сложного.....
Я подключаюсь к Raspberry Pi через SSH со своего ноутбука... Переадресация X работает нормально, поскольку я могу запускать приложения X из командной строки без каких-либо проблем.
Я использую Apache2 на Raspberry Pi и создал пользовательский интерфейс для этой программы, в который можно вставлять текст, загружать текстовые файлы или файлы PDF.
Текст преобразуется в речь с помощью espeak, который сохраняет вывод в файле WAV.
Теперь проблема в том, что я использую:
system("xmms2 play file.wav &")
в коде C ........просто краткое описание
он компилируется.....когда я пробую его с веб-страницы, он выдает ошибки:
Gtk-WARNING **: cannot open display: localhost:10.0
cannot start xmms2d.....failed to start xmms2 server
Я даже попробовал другой аудиоплеер под названием Aqualung, и он сработал один раз, но на следующий день, когда я перезагрузил компьютер, он больше не работает.
Я погуглил и сделал все, чтобы export DISPLAY=:0.0
убедиться, что имя хоста на клиенте и хосте не является localhost, но безуспешно
Поэтому я думаю, что, возможно, я что-то не добавил в программу на языке C, может быть, заголовочный файл, который нужно добавить, или что-то в этом роде... На моем Raspberry установлен Gtk+...
Или, может быть, мне не стоит делать это как программу на C, а сделать все на bash или php....
Если я использую aplay для воспроизведения wav-файла, я получаю звуковой вывод, единственное отличие в том, что мне нужно что-то с командной строкой и пользовательским интерфейсом. Чтобы я мог отправлять команды из программы, а пользователь также мог приостанавливать и воспроизводить файл, когда захочет.
Пожалуйста, нужен совет... вот код
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <wiringPi.h>
char readcmd(void) //reading from text file /home/pi/cmdrdy.txt first character is read
{ //whenever text is received a 1 is written to this file, 2 for file received
FILE *stream;
int ch;
if( (stream = fopen("/home/pi/txtrdy.txt", "r")) == NULL )
return 0;
ch = fgetc( stream );
fclose( stream );
return (ch-'0');
}
void reset()
{
FILE *ft;
char ch;
ft = fopen( "/home/pi/cmdrdy.txt", "w" );
ch = '0';
fprintf(ft, "%c", ch );
fclose(ft);
}
void checktxt(){
if(readcmd() == 1)
{
system("espeak -v en -f /home/pi/book.txt -w /home/pi/text.wav &");
reset(); //to reset the text received flag to 0
system("xmms2 play /home/pi/text.wav &");
}
if(readcmd2() == 2)
{
system("pdftotext -layout /home/pi/upload/*.pdf /home/pi/converted.txt &");
delay(300);
system("espeak -v en -f /home/pi/converted.txt -w /home/pi/book.wav &");
delay(500);
system("sudo rm /home/pi/converted.txt");
system("sudo rm /home/pi/upload/*.pdf");
system("xmm2 play /home/pi/book.wav &");
}
}
void main(){
while(1){
checktxt();
}
}
решение1
Я сам с этой проблемой не сталкивался, но могу рискнуть сделать обоснованное предположение, почему это происходит: судя по всему, xauth не распространяется на дочерний процесс. На самом деле, я не смог найти XAUTHORITY в выводе
export -p
на Raspberry с ОС Raspian.
Я не смог точно установить, погуглив, действительно ли это так даже для других ОС, но это так легко попытаться исправить, что это стоит попробовать в любом случае. Я предлагаю вам заменить команду исполняемым скриптом, назовите его /home/my_name/bin/my_script, сделав исполняемым с помощью, конечно chmod 755
, в который вы поместите следующие 3 строки кода:
#!/bin/bash
export XAUTHORITY=/home/my_name/.Xauthority
xmms2 play file.wav &
Поскольку system
вызов сначала разветвляется, а затем запускает экземпляр оболочки с переменными окружения вызывающего, ваша программа знает (и доказывает, что знает), что ваш дисплей — это 10.0
, но доступ к нему должен быть предоставлен внутри подоболочки, в которой xmms2
выполняется команда. Эта модификация гарантирует вам это.
решение2
Я немного изменил код выше и добавил в него совет
включать
включать
включать
включать
typedef enum {WAIT, TEXT, PDF, DOC}STATES; typedef char STATE; STATE current_state;
char readcmd() //чтение из текстового файла /home/pi/cmdrdy.txt первый символ считан { FILE *stream; int ch; if( (stream = fopen("/home/pi/cmdrdy.txt", "r")) == NULL ) return 0; ch =fgetc(stream); fclose(stream); return (ch-'0'); }
void reset()
{ ФАЙЛ *ft; char ch; ft = fopen( "/home/pi/cmdrdy.txt", "w" ); ch = '0'; fprintf(ft, "%c", ch ); fclose(ft); }
char convtts() { //convert text to speech
system("espeak -v en -f /home/pi/book.txt -w /home/pi/text.wav &");
return (0);
}
char pdf2txt(){ //convert pdf to text
system("pdftotext -layout /usr/lib/cgi-bin/upload/*.pdf /home/pi/converted.txt");
return (0);
}
char pdftts(){ //convert converted text to speech
system("espeak -v en -f /home/pi/converted.txt -w /home/pi/book.wav &");
return(0);
}
void state_machine(void){ //creating a state machine
switch(current_state){
case WAIT:
if(readcmd() == 1)
{
reset();
current_state = TEXT;
}
if(readcmd() == 2)
{
reset();
current_state = PDF;
}
break;
case TEXT:
convtts();
while(convtts()==1);
system("/home/pi/bin/text_script");
current_state = WAIT;
break;
case PDF:
pdf2txt();
while(pdf2txt()==1);
pdftts();
while(pdftts()==1);
system("/home/pi/bin/book_script");
system("sudo rm /usr/lib/cgi-bin/upload/*.pdf");
current_state = WAIT;
break;
} }
void main(){
while(1){
state_machine();
} }
И это работает как по маслу...спасибо огромное