Hallo, danke für Sticky. Ist dann schon mein Zweiter neben dem im T-Hack Forum, wo ich das Frontend für mein jetziges Internetradio im X300T programmiert habe.
Ich bin wieder weg vom mpg123. Denn der Trick mit dem verzögerten abspielen klappt nur bei wenigen Sendern, ist mir aber erst später aufgefallen, da ich beim Testen immer ffn comedy gehört hatte...
Jetzt nutze ich den mpd, welchen ich per mpc steuere.:
Code:
apt-get update
apt-get upgrade
apt-get install mpd mpc
Das upgrade war ~118MB und benötigt, einiges an Platz. Ich habe dafür dann die 2GB SD-Karte gegen eine 8GB SD-Karte ausgetauscht..
Meine Scripte und Programme liegen alle unter /var/scripte.
Nach der Installation von mpd und mpc wird eine playlist benötigt. Diese habe ich nach /var/lib/mpd/playlists kopiert. Die Rechte gleich wieder auf 644.
Code:
chmod 644 /var/lib/mpd/playlists/radiosender.m3u
Diese sieht zur Zeit so aus:
Code:
http://rs26.stream24.org:80/stream
http://rs35.stream24.org:80/stream
http://stream.hoerradar.de:80/mp3-128_hra-nds
http://ndrstream.ic.llnwd.net/stream/ndrstream_ndr2_hi_mp3
http://ndrstream.ic.llnwd.net/stream/ndrstream_n-joy_hi_mp3
http://rbb.ic.llnwd.net/stream/rbb_fritz_mp3_m_a
http://d85195728.i.tis.core005.cdn.streamfarm.net:80/22005mdrsputnik/live/3087mdr_sputnik_live/de_96.mp3
http://www.energyradio.de/rock
http://www.energyradio.de/berlin
In mpd dann noch die Konfiguration anpassen.
Bei audio_output habe ich folgendes angepasst:
Code:
audio_output {
type "alsa"
name "My ALSA Device"
auto_resample "no"
device "hw:0,0" # optional
format "44100:16:2" # optional
mixer_device "default" # optional
mixer_control "PCM" # optional
mixer_index "0" # optional
period_time "5000" # Soll Knackser minimieren, experimentiere noch mit dem Wert
}
Hinweis: Laut meinen Recherchen soll der analoge Audioausgang nur aktiv sein, wenn keine HDMI Verbindung steht.
Anschließend schonmal per
Code:
mpc load radiosender
die Liste in mpd einlesen. Diese Liste merkt sich mpd auch über einen Neustart hinaus, bzw hängt sie bei jedem Aufruf zusätzlich hinten dran.
Testen, ob das abspielen läuft:
spielt den ersten Eintrag in der Liste ab.
beendet die Wiedergabe, bzw. pausiert, denn mit
wird die Wiedergabe des zuletzt gewählten Senders fortgesetzt.
Wenn das alles läuft, kann man sich der externen Ansteuerung widmen. Welche bei mir aus 3 Programmen besteht.
1. Entgegennahme der Befehle vom AVR:
Code:
// Compile with: GCC /var/scripte/empfangen.c -o /var/scripte/empfangen
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BAUDRATE B19200
char MODEMDEVICE[]= "/dev/ttyAMA0"; // Schnittstelle
char FILEDEVICE[]= "/tmp/empfang.txt"; // letztes Empfangenen in Datei schreiben, für evtl. BASH-Auswertung
//char AUSFUEHREN[32]= "/var/scripte/seriell.sh"; // BASH Script zum Auswerten der Daten
//char RADIOSPIELEN[32]="nice -1 /var/scripte/radio2.sh &"; // BASH Script zum abspielen
//char RADIODEVICE[32]= "/var/scripte/radiosender"; // Senderliste
char FARBDEVICE[]="/tmp/webif.farbe"; // Dateiname für php Farben
//char SENDERDEVICE[32]="/tmp/radiourl"; // URL zum abspielen für mpg123 ablegen
/*
Sx x=0 aktuellen Sender neu abspielen Nach Stop oder zum neu puffern, x>49 Sender x-48 abspielen
Bx x=0 abspielen stoppen, x=1 Senderliste neu laden, x=2 mpd neu starten
Px x=0 einen Senderplatz zurück x=1 einen Senderplatz hoch
Frrggbb gesetzte Farben für php in Datei ablegen
resetreset Reboot des Raspi
*/
char eingang[255]="";
char d[1]="";
int anzahl=0;
int laenge=0;
int logg=0;
int fd; // File descriptor
int sender;
struct termios newtio={};
unsigned char send()
{ int i;
int fd1;
char ret;
/* Zum Schreiben öffnen */
fd1 = open (FILEDEVICE, O_WRONLY|O_CREAT|O_TRUNC);
if (fd1 == -1)
exit (-1);
write (fd1, eingang, laenge);
close (fd1);
system("chmod 644 /tmp/empfang.txt");
if (logg==1){
printf("AVR: %s\n",eingang);
}
//system(AUSFUEHREN);
for(i=0; i < laenge; i++)
{
eingang[i] = 0;
}
laenge=0;
}
unsigned char radioein()
{
//int i=0;
char nummer[1];
// char sender_name[30]="";
char befehl[255]="";
/* FILE *f;
char Text[300]="";
f = fopen(RADIODEVICE,"r");
if(f==NULL)
{
printf("Fehler beim Oeffnen! Bitte ueberpruefe deinen Pfad!\n");
}
i=0;
while( fgets(Text, sizeof(Text), f) !=0 ){
i++;
if (i==sender){
strcpy(sender_name,"1");
strcat(sender_name,Text);
if (logg==1){
printf("Sendername: %s\n",sender_name);
}
// system(RADIOSPIELEN);
strcpy(befehl,"/var/scripte/senden ");
strcat(befehl,sender_name);
system(befehl);
}
}
fclose(f);
*/
sprintf(nummer,"%d",sender);
strcpy(befehl,"mpc -q play ");
strcat(befehl,nummer);
system(befehl);
}
unsigned char initmpd()
{
int i=0;
system("mpc stop");
system("mpc playlist > /tmp/mpdlist");
sleep(1);
FILE *f;
char Text[300]="";
char Text1[70]="";
char Text2[7]="volume";
f = fopen("/tmp/mpdlist","r");
anzahl=0;
if(f!=NULL){
fgets(Text, sizeof(Text), f);
if(strlen(Text)<2){
fclose(f);
system("mpc clear");
system("mpc load radiosender");
initmpd();
return;
}else{
anzahl=1;
while( fgets(Text, sizeof(Text), f) !=0 ){
anzahl++;
}
}
fclose(f);
if(anzahl>200){
initmpd();
return;
}
}
}
unsigned char auswerten()
{ int i;
int fd1;
int zeile;
char ret;
char farbe[6]="";
/* Zum Schreiben öffnen */
if ((strcmp(eingang,"resetreset") ==0 )){
system("reboot");
}
if ((strcmp(eingang,"B1") ==0 )){
initmpd();
}
if (eingang[0] == 70){ // F
fd1 = open (FARBDEVICE, O_WRONLY|O_CREAT|O_TRUNC); //|O_TRUNC, S_IRUSR|S_IWUSR
if (fd1 == -1)
exit (-1);
for(i=0; i<=6; i++)
{
farbe[i]=eingang[i+1];
}
write (fd1, farbe, 6);
close (fd1);
system("chmod 644 /tmp/webif.farbe");
}
if (eingang[0] == 83){ // S
zeile=eingang[1]-48; //Werte von 48-255 = 207 Sender
if (zeile == 0){ // 0
system("mpc -q play");
}else if (zeile<=anzahl){
sender=zeile;
radioein();
}
}
if (eingang[0] == 80){ // P
if (eingang[1]==49){ //1
sender++;
if (sender>anzahl){
sender=1;
}
}else{
sender--;
if (sender<1){
sender=anzahl;
}
}
radioein();
}
if (eingang[0] == 66){ // B
if (eingang[1]==48){ //0
system("mpc stop");
sleep(1);
// system("/var/scripte/senden 0"); // Macht jetzt mpcout für tatsächlichen Zustand
}
if (eingang[1]==49){ //1 Senderliste neu laden
system("mpc clear");
initmpd();
}
if (eingang[1]==50){ //2 mpd neu starten
system("/etc/init.d/mpd restart");
}
}
eingang[laenge]=10; //Zeilenvorschub
laenge++;
send();
}
unsigned char receive()
{
int res;
unsigned char buffer;
res = read(fd, &buffer, 1);
return buffer;
}
int init()
{
/*** Init ***/
//O_RDONLY, O_WRONLY or O_RDWR -
//O_NDELAY (geht weiter, wenn keine Daten da sind und gibt "-1" zurueck)
// man 2 open fuer mehr Infos - see "man 2 open" for more info
// O_NOCTTY No ControllTeleType
/*fd1 = open(FILEDEVICE, O_WRONLY);
if (fd1 < 0){
printf("Fehler beim oeffnen von %s\n", FILEDEVICE);
exit(-1);
}*/
fd = open(MODEMDEVICE, O_RDONLY | O_NOCTTY);
if (fd < 0){
printf("Fehler beim oeffnen von %s\n", MODEMDEVICE);
exit(-1);
}
memset(&newtio, 0, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; //setzt die neuen Porteinstellungen
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = 0; /* set input mode (non-canonical, no echo, ...) */
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VMIN] = 1; /* blocking read until 1 chars received */
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
return fd;
}
int main(int argc, char** argv)
{
char c;
init();
sleep(8); //warten bis mpd gestartet ist
initmpd();
while (1)
{
c=receive();
if((c==13)){
auswerten();
}else if(c>13){
eingang[laenge]=c;
laenge++;
if (laenge >254){
auswerten();
}
}
}
close (fd);
return 0;
}
2. Befehle zum AVR senden:
Code:
// Compile with: GCC /var/scripte/senden.c -o var/scripte/senden
//#include <iostream>
//using namespace std;
#include <sys/types.h> //nicht benötigtes scheint keinen Platz zu verschwenden...
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#define BAUDRATE B19200
char MODEMDEVICE[]= "/dev/ttyAMA0"; // !!!
int fd; // File descriptor
struct termios newtio={};
unsigned char send(char c)
{
int res=write(fd, &c, 1);
if (res<0) printf("Fehler beim Senden\n");
return res;
}
int init()
{
/*** Init ***/
//O_RDONLY, O_WRONLY or O_RDWR -
//O_NDELAY (geht weiter, wenn keine Daten da sind und gibt "-1" zurueck)
// man 2 open fuer mehr Infos - see "man 2 open" for more info
// O_NOCTTY No ControllTeleType
fd = open(MODEMDEVICE, O_WRONLY | O_NOCTTY);
if (fd < 0){
printf("Fehler beim oeffnen von %s\n", MODEMDEVICE);
exit(-1);
}
memset(&newtio, 0, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; //setzt die neuen Porteinstellungen
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = 0; /* set input mode (non-canonical, no echo, ...) */
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VMIN] = 1; /* blocking read until 1 chars received */
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
return fd;
}
int main(int argc, char** argv)
{
char c;
char vBuf[80]="",*pBuf;
char buffer [80];
int i=0;
init();
if (argc == 1) { //Wenn nichts angegeben, dann Uhrzeit und Datum senden
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
strftime (buffer,80,"U%H:%M:%S",timeinfo); //Uhh:mm:ss
pBuf=buffer;
strcat(pBuf,"\r");
while(pBuf && *pBuf) //Zeichen einzeln senden
send(*pBuf++);
strftime (buffer,80,"D%d.%m.%y",timeinfo); //Dtt.mm.yy
pBuf=buffer;
strcat(pBuf,"\r");
sleep(1);
while(pBuf && *pBuf) //Zeichen einzeln senden
send(*pBuf++);
}else{ //Sonst Parameter einlesen und senden
if(strlen(argv[1])>75){ //Puffer im AVR ist auf 80 gestellt
strncpy(buffer,argv[1],76);
buffer[76]='\0';
}else{
strcpy(buffer,argv[1]);
if (argc >2){
for (i=2;i<argc;i++){
if(strlen(buffer)+strlen(argv[i])>75){
strcat(buffer," ");
strncat(buffer,argv[i],(76-strlen(buffer)));
buffer[76]='\0';
break; //exit for in c...
}else{
strcat(buffer," ");
strcat(buffer,argv[i]);
}
}
}
}
pBuf=buffer;
strcat(pBuf,"\r"); //CHR(13) anfügen, damit der AVR auswertet
while(pBuf && *pBuf){ //Zeichen einzeln senden
send(*pBuf++);
}
}
close (fd);
return 0;
}
3. mpd überwachen und Status, bzw Titel zum AVR senden.
Code:
// Compile with: GCC /var/scripte/mpcout.c -o /var/scripte/mpcout
//#include <sys/types.h>
//#include <sys/stat.h>
//#include <fcntl.h>
//#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <unistd.h>
char Textalt[75]="";
//char SENDERDEVICE[32]="/tmp/mpcout";
unsigned char aktualisieren()
{
int i=0;
int o=0;
char befehl[255]="";
system("mpc current > /tmp/mpcout");
sleep(1);
FILE *f;
char Text[300]="";
char Text1[75]="";
// char Text2[7]="volume"; //Ausgabe, wenn nichts gespielt wird - wegen Parameter current nicht mehr nötig.
f = fopen("/tmp/mpcout","r");
if(f!=NULL){
fgets(Text, sizeof(Text), f);
if(strlen(Text)<2){
strcpy(Text1,"");
if((strcmp(Text1, Textalt)) != 0){
strcpy(Textalt, Text1);
system("/var/scripte/senden 0");
}
}else{
o=0;
for (i=0;i<strlen(Text);i++){
Text1[o]=Text[i];
//if (Text[i]==32||Text[i]==45||Text[i]==46||Text[i]>=48&&Text[i]<=59||Text[i]>=65&&Text[i]<=90||Text[i]>=97&&Text[i]<=122||Text[i]>=127&&Text[i]<=252){ //Parsen
o++;
//}
if (o>74){
break;
}
}
Text1[o]='\0';
if((strcmp(Text1, Textalt)) != 0){
strcpy(Textalt, Text1);
// if(strncmp(Text,Text2,6) != 0){ //wegen Parameter current nicht mehr nötig.
strcpy(befehl,"/var/scripte/senden '1"); // \" funktioniert nicht, ' schon
strcat(befehl,Text1);
strcat(befehl,"'");
system(befehl);
// } //wegen Parameter current nicht mehr nötig.
}
}
}
fclose(f);
}
int main(int argc, char** argv)
{
char c;
/*f (argc > 1){
logg=1;
printf("Logging Modus ein %s\n",LOGDEVICE);
}*/
while (1)
{ sleep(2);
aktualisieren();
}
return 0;
}
Kompiliert habe ich die Programme per gcc. Wenn der Code für den einen oder anderen optimierungsbedürftig aussieht, kann er das gerne machen. Diskussionen über C-Programmierung bitte in einem anderen Thread. Ich bin froh, dass es bisher fehlerfrei läuft. C gehört nicht zu meinen Favoriten.
Aufgerufen werden diese in der /etc/rc.local: (Ausschnitt)
Code:
nice -1 /var/scripte/empfangen &
nice -1 /var/scripte/mpcout &
/etc/init.d/mpd restart
/etc/init.d/apache2 restart
aplay /usr/games/start.wav
Der vorletzte Befehl startet den Apache nochmal neu, was hier eigentlich nicht von nutzen ist, und der letzte siganlisiert dann über die Lautsprecher, dass der Raspi fast fertig hochgefahren ist.
Hinweis:
Ich nutze die UART auf der Stiftleiste. Für einen USB-Seriell Adapter sind folgende Schritte nicht notwendig!
Damit die UART frei ist, müssen 2 Dateien angepasst werden. Achtung: Vorher sichern. Wenn was schief geht, kann ich die SD-Karte in meinem NAS mounten und die Sicherungen zurückspielen...
/boot/cmdline.txt:
Code:
dwc_otg.lpm_enable=0 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
/ect/inittab: Folgende Zeile auskommentieren
Code:
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
zu
Code:
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
Und natürlich auch alle anderen Zeilen, welche auf ttyAMA0 zugreifen wollen.
Lesezeichen