我正在尝试编写一个程序,该程序将使用树莓派上的开源程序用 C 语言读取文本和 pdf 文档。
该程序很简单,没有什么复杂的......
我正在通过笔记本电脑的 ssh 连接到树莓派...X 转发工作正常,因为我可以从命令行启动 X 应用程序而没有任何问题。
我在树莓派上使用 apache2,并且为该程序制作了一个用户界面,您可以在其中粘贴文本、上传文本文件或 pdf 文件。
使用 espeak 将文本转换为语音,然后将输出保存为波形文件。
现在的问题是我用的是:
system("xmms2 play file.wav &")
在 C 代码中......只是一个简短的描述
它编译.....当我从网页上尝试它时,它显示错误:
Gtk-WARNING **: cannot open display: localhost:10.0
cannot start xmms2d.....failed to start xmms2 server
我甚至尝试了另一个名为 aqualung 的音频播放器,它工作了一次,但第二天当我重新启动计算机时,它就不再工作了。
我在 google 上搜索,并做了所有事情,以export DISPLAY=:0.0
确保客户端和主机上的主机名不是本地主机,但没有成功
所以我想也许我在 C 程序中没有添加一些东西,也许需要添加一个头文件或类似的东西.....我的树莓派上安装了 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
在运行 Raspian 的 Raspberry 上。
通过谷歌搜索,我无法确定其他操作系统是否也存在这种情况,但尝试修复这个问题非常简单,因此值得一试。我建议您用可执行脚本替换该命令,将其命名为 /home/my_name/bin/my_script,当然chmod 755
,通过以下 3 行代码将其变为可执行文件:
#!/bin/bash
export XAUTHORITY=/home/my_name/.Xauthority
xmms2 play file.wav &
由于system
调用首先派生,然后使用调用者环境变量启动 shell 实例,因此您的程序知道(并证明它知道)您的显示是10.0
,但必须在xmms2
执行命令的子 shell 中授予对它的访问权限。此修改可确保您做到这一点。
答案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();
} }
而且效果非常好......非常感谢