
Ich versuche, mit Open-Source-Programmen auf dem Raspberry Pi ein Programm zu schreiben, das beim Lesen von Text- und PDF-Dokumenten in C hilft.
das Programm ist einfach, nichts kompliziertes.....
Ich verbinde mich von meinem Laptop aus per SSH mit dem Raspberry Pi. Die X-Weiterleitung funktioniert einwandfrei, da ich X-Anwendungen problemlos von der Befehlszeile aus starten kann.
Ich verwende Apache2 auf dem Raspberry Pi und habe für dieses Programm eine Benutzeroberfläche erstellt, in der Sie Text einfügen und Textdateien oder PDF-Dateien hochladen können.
Der Text wird mit espeak in Sprache umgewandelt und die Ausgabe in einer Wave-Datei gespeichert.
Jetzt besteht das Problem darin, dass ich Folgendes verwende:
system("xmms2 play file.wav &")
im C-Code ........nur eine kurze Beschreibung
es wird kompiliert.....wenn ich es von der Webseite aus versuche, werden Fehler angezeigt:
Gtk-WARNING **: cannot open display: localhost:10.0
cannot start xmms2d.....failed to start xmms2 server
ich habe sogar einen anderen Audioplayer namens Aqualung ausprobiert, der einmal funktionierte, aber am nächsten Tag, als ich den Computer neu startete, funktionierte er nicht mehr.
ich habe gegoogelt und alles getan, um export DISPLAY=:0.0
sicherzustellen, dass der Hostname auf dem Client und Host nicht localhost ist, aber kein Erfolg
Ich denke also, dass es vielleicht etwas gibt, was ich im C-Programm nicht hinzugefügt habe, möglicherweise eine Header-Datei, die hinzugefügt werden muss oder etwas in der Art … Auf meinem Raspberry ist Gtk+ installiert …
Oder vielleicht sollte ich es nicht als C-Programm machen, sondern alles in Bash oder PHP …
Wenn ich Aplay zum Abspielen der WAV-Datei verwende, erhalte ich eine Tonausgabe. Der einzige Unterschied besteht darin, dass ich etwas mit Befehlszeile und Benutzeroberfläche benötige. So kann ich Befehle aus dem Programm senden und der Benutzer kann die Datei jederzeit anhalten und abspielen.
Bitte, ich brauche einen Rat.... hier ist der Code
#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();
}
}
Antwort1
Ich bin selbst noch nicht auf dieses Problem gestoßen, kann aber eine fundierte Vermutung darüber anstellen, warum dies geschieht: So wie es aussieht, erstreckt sich xauth nicht auf den untergeordneten Prozess. Tatsächlich konnte ich XAUTHORITY in der Ausgabe von nicht finden
export -p
auf einem Raspberry mit Raspian.
Ich konnte durch Googeln nicht mit Sicherheit feststellen, ob dies auch bei anderen Betriebssystemen der Fall ist, aber es ist so einfach, das Problem zu beheben, dass es sich auf jeden Fall lohnt. Ich schlage vor, Sie ersetzen den Befehl durch ein ausführbares Skript, nennen es /home/my_name/bin/my_script, das chmod 755
natürlich durch Ausführen ausführbar gemacht wird und in das Sie die folgenden 3 Codezeilen einfügen:
#!/bin/bash
export XAUTHORITY=/home/my_name/.Xauthority
xmms2 play file.wav &
Da der system
Aufruf zuerst eine Aufspaltung durchführt und dann eine Instanz der Shell mit den Umgebungsvariablen des Aufrufers startet, weiß Ihr Programm (und beweist, dass es das weiß), dass Ihre Anzeige 10.0
, aber der Zugriff darauf muss innerhalb der Subshell gewährt werden, in der der Befehl xmms2
ausgeführt wird. Diese Änderung stellt dies sicher.
Antwort2
Ich habe den obigen Code jetzt ein wenig modifiziert und die Hinweise darin eingefügt
enthalten
enthalten
enthalten
enthalten
typedef enum {WAIT, TEXT, PDF, DOC}STATES; typedef char STATE; STATE aktueller_Status;
char readcmd() //Lesen aus der Textdatei /home/pi/cmdrdy.txt, erstes Zeichen wird gelesen { 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()
{ DATEI *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();
} }
Und es funktioniert wie am Schnürchen... tausend Dank