Themabewertung:
  • 3 Bewertung(en) - 3.67 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Ein minimales Internetradio für alte und neue Raspberrys
#41
Hallo Bernhard,
Danke Dir für das Aufzeigen der prinzipiellen Vorgehensweise!

Das wird mich in den nächsten Tagen beschäftigen - werde mich melden, wenn ich kein Land mehr sehe.
Grüße aus Wassenberg,
Norbert.
Zitieren
#42
Kein Land mehr sehen ist gut, ich bin am Ertrinken Norbert. Das FLTK Programm läuft bei mir auf Solaris. Auch das Radiopaket funktioniert. Ich kann umschalten und die Lautstärke andern! Was aber ist das mit *irgwndwas und was sind call back Funktionen? Ist das soetwas wie eine Interrupt Service Routine oder was muss ich darunter Verstehen?
Zitieren
#43
Hallo Otto,

Zitat:
In FlTk the way you specify the behavior of most things (like what happens when you press a button) is by telling FlTk a function (called a “callback”) that should be called when the thing happens.  
Zitat Ende

Callback ruft eine Funktion auf, wenn eine bestimmte Aktion erfolgt (z. B. das Drücken einer Taste).
Der Benutzer / Programmierer legt den Namen der Funktion fest und programmiert deren Aufgabe. 
Ob das Interrupt gesteuert stattfindet weiss ich nicht.

Ich kann nur raten klein anzufangen mit z.B. einem Knopf und zu beobachten, welche Wirkungen verschiedene Parameter haben.
Und es selbst zu testen!
Die Fluid Hilfe lesen und im Internet nach weiteren Informationen / Beispiele zu suchen.
Das tue ich auch....
Nicht zu vergessen - ein gutes C-Buch (gibt es auch online) kann helfen.
Die Zusammenhänge zwischen VLC, Betriebssystem und dem eigenem Programm zu begreifen und umzusetzen,
dass ist schon kompliziert.
Grüße aus Wassenberg,
Norbert.
Zitieren
#44
(04.11.2018, 19:31)OttoBerger schrieb: Was aber ist das mit *irgwndwas 

Das sind Zeiger auf eine Variable im Speicher. Ich wollte jetzt den Hex-Editor anwerfen und das alles genau aufzeigen, da fiel mir folgendes Video in die Hände: BITTE ALLE ANSCHAUEN!



Zu call back - Das hat Norbert ja schon erklärkt, im Prinzip werden die Angesprungen wie eine ISR, also wenn irgendetwas passiert, sprich die Maus geklickt wird, der Butten gedrückt, das Fenster verschoben wird, usw. 
Man kann in FLTK eine Funktion sich ausdenken und deren Namen mit einem Ereignis verknüpft registrieren. Die Ereignisse sind wie Software-Interrupts, die Funktionen die Handlerfunktionen dazu. Zusätzlich kann man den Funktionen eine Variable, ein Objekt oder eine Datenstruktur (als Zeiger im Speicher) mitgeben und diese dann bei Aufruf manipulieren (also zum Beispiel eine Variable ändern die den Sendernamen beinhalten soll).
Ich denke das ist verstehbar?
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung. 
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")
Zitieren
#45
(04.11.2018, 20:29)norbert_w schrieb: Die Zusammenhänge zwischen VLC, Betriebssystem und dem eigenem Programm zu begreifen und umzusetzen,
dass ist schon kompliziert.

Wenn da etwas unklar ist, sofort hier nachfragen Norbert! Ich will das das Zusammenspiel aller Komponenten von jedem Nutzer verstanden wird. Keine Scheu!

Gruß
Bernhard
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung. 
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")
Zitieren
#46
Hallo zusammen,

jetzt habe ich mein textbasiertes Frontend komplett auf die 'curses.h'-Bibliothek umgestrickt, jetzt tut es auch, was es soll. Na ja, wenigstens fast:


.png   Bildschirmfoto vom 2018-11-05 21-28-41.png (Größe: 25,62 KB / Downloads: 526)

Wie in der untersten, cyanfarben dargestellten Zeile zu sehen, mogelt sich da immer ein Zeichen des ersten abgesetzten Kommandos ein, obwohl ich eigentlich diese Stelle vor der nächsten Textausgabe mit Leerzeichen überschreibe.
Manchmal werden auch nicht alle Zeichen überschrieben!

Auf diese beiden Effekte kann ich mir momentan noch keinen Reim machen.
Ich muss noch in der Doku zu 'curses.h' weiterlesen, ob es da eine Entsprechung zum 'clreol' (clear end of line) von Turbo-Pascal gibt.

Hier mal der Code:

Code:
/* Frontend V3 */
#include <curses.h>
int main (void) {
 int c;
 initscr ();
 start_color();
 init_pair(1,COLOR_YELLOW,COLOR_BLUE);
 init_pair(2,COLOR_GREEN,COLOR_BLUE);
 init_pair(3,COLOR_RED,COLOR_BLUE);
 init_pair(4,COLOR_CYAN,COLOR_BLUE);
 attrset(A_BOLD|COLOR_PAIR(2));
 keypad (stdscr, TRUE);
 noecho();
 //Bildschirm füllen
 int Zeile, Spalte;
 for( Zeile = 0; Zeile < 26; Zeile++ )
 {
   for( Spalte = 0; Spalte < 81; Spalte++ )
   {
   mvprintw(Zeile,Spalte," ");
   }
 }
 mvprintw(2,15,"Textbasiertes Frontend für Internetradio");
 attrset(A_BOLD|COLOR_PAIR(3));
 mvprintw(5,10,"q:");
 attrset(A_BOLD|COLOR_PAIR(1));
 mvprintw(5,13,"Beenden");
 attrset(A_BOLD|COLOR_PAIR(3));
 mvprintw(7,10,"+:");
 attrset(A_BOLD|COLOR_PAIR(1));
 mvprintw(7,13,"Lauter");
 attrset(A_BOLD|COLOR_PAIR(3));
 mvprintw(9,10,"-:");
 attrset(A_BOLD|COLOR_PAIR(1));
 mvprintw(9,13,"Leiser");
 attrset(A_BOLD|COLOR_PAIR(3));
 mvprintw(11,10,"N:");
 attrset(A_BOLD|COLOR_PAIR(1));
 mvprintw(11,13,"Nächster Sender");
 attrset(A_BOLD|COLOR_PAIR(3));
 mvprintw(13,10,"V:");
 attrset(A_BOLD|COLOR_PAIR(1));
 mvprintw(13,13,"Vorheriger Sender");
 attrset(A_BOLD|COLOR_PAIR(3));
 mvprintw(15,10,"P:");
 attrset(A_BOLD|COLOR_PAIR(1));
 mvprintw(15,13,"Pause");
 attrset(A_BOLD|COLOR_PAIR(4));
 while ((c = getch ()) != 'q') {
   switch (c) {
   case 'v':
   case 'V':
     mvprintw (20,10,"                                        ");
     mvprintw (20,10,"Gewählte Funktion: Vorheriger Sender");
     //Hier folgt Funktionsaufruf 'Vorheriger Sender'
     break;
   case 'N':
   case 'n':
     mvprintw (20,10,"                                        ");
     mvprintw (20,10,"Gewählte Funktion: Nächster Sender");
     //Hier folgt Funktionsaufruf 'Nächster Sender'
     break;
   case '+':
     mvprintw (20,10,"                                         ");
     mvprintw (20,10,"Gewählte Funktion: Lauter");
     //Hier folgt Funktionsaufruf 'Lauter + 2%'
     break;
   case '-':
     mvprintw (20,10,"                                         ");
     mvprintw (20,10,"Gewählte Funktion: Leiser");
     //Hier folgt Funktionsaufruf 'Leiser - 2%'
     break;
   case 'P':
   case 'p':
     mvprintw (20,10,"                                         ");
     mvprintw (20,10,"Gewählte Funktion: Pause");
     //Hier folgt Funktionsaufruf 'Pause'
     break;
   }
 }
 endwin ();
 return 0;
}
Ich probiere das Ganze derzeit an meinem Laptop aus, hier habe ich (noch) kein VLC installiert, daher sind die Stellen der Switch-Case-Verzweigung mit Kommentaren versehen, an welchen die Systemaufrufe für VLC eingefügt werden müssen.

Das ganze kann man mit Sicherheit eleganter lösen, es sind halt meine ersten Ausflüge in die Programmierung mit C/C++.


Grüße

Martin
Zitieren
#47
Hallo zusammen,

heute Abend habe ich mir das Internetradio nach der Anleitung bzw. dem Installationstool von Bernhard installiert.

Ebenso habe ich mir mein Textfrontend auf dem raspi neu compiliert.

Es läuft auch:

.png   Bildschirmfoto vom 2018-11-10 20-40-52.png (Größe: 9,4 KB / Downloads: 483)

Aber sobald ich eine Taste drücke, passiert dies:

   

Gestartet habe ich das Progrämmchen im Verzeichnis /home/iRadio/

Weiterhin ist mir aufgefallen, dass nach einem reboot vlc nicht immer startet Huh 


Grüße

Martin
Zitieren
#48
Hallo Martin,

wenn der vlcd im rc.local drin ist, dann wird er nach einem reboot auch gestartet und erscheint in der Prozesstabelle. Wenn der Prozess sporadisch beendet wird, dann hat das andere Gründe, die ich aber mangels Zugriff auf dein System nicht genau nennen kann. Hier musst Du selbst mal auf die Suche gehen.

Was dein Konsolenfrontend angeht, hier musst Du die Meldungen der beteiligten Prozesse unterdrücken damit sie dein Fenster nicht zerlegen.
Verbose/silent-Modus könnten eine Lösung sein oder auch die Ausgaben auf einen anderen Ausgabestrom umleiten.
Schaue für genaueres bitte in die manpages und in eines der Systemprogrammierbücher  die ich empfohlen habe. 

Wenn Du nicht weiterkommst, kannst mir auch die Sourcen deines Programms per PN oder Mail zukommen lassen, dann schaue ich mal in einer ruhigen Minute drüber und kann vielleicht mehr Hilfe anbieten.

Gruß
Bernhard
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung. 
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")
Zitieren
#49
Hallo Bernhard und Mitleser,

ich habe ein wenig weiter programmiert und z.B. einen Timer eingebunden.
Aber so langsam stoße ich an meine Grenzen....

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <iostream>

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Text_Display.H>
#include <FL/Fl_Button.H>

#include <FL/Fl_Group.H>
#include <FL/Fl_Dial.H>
#include <FL/Fl_Roller.H>
#include <FL/Fl_Output.H>
#include <FL/fl_draw.H>
#include <FL/Enumerations.H>
#include <FL/Fl_Widget.H>
using namespace std;

Fl_Output* zeile_1;
Fl_Output* zeile_2;

//static int count = 0;
int sender_prev, volume_prev;
int count = 0;
char Text_1 [30] = "Taste drücken";
char Text_2 [30] = "L ä u f t";
char Text_3 [30] = "F e r t i g";

char Text_10 [30] = "weiss noch nicht...";

char const* Anzeige_1 = Text_1;
char const* Anzeige_2 = Text_10;

void anz_auffrischen(Fl_Widget *, void *) {
string text_stream;     
//system("echo \"prev\" | nc 127.0.0.1 9294 -N");
FILE *text_now_playing = popen("echo \"info\" | nc 127.0.0.1 9294 -N | grep now_playing:", "r");
pclose(text_now_playing);
//ab hier ??? was tun
}

void lauter_leiser(Fl_Dial* v, void *) {
 
if (((Fl_Dial*) v)->value() < volume_prev) {
     volume_prev = (((Fl_Dial*) v)->value() );
     system("echo \"voldown 1\" | nc 127.0.0.1 9294 -N");
}

if (((Fl_Dial*) v)->value() > volume_prev) {
     volume_prev = (((Fl_Dial*) v)->value() );
     system("echo \"volup 1\" | nc 127.0.0.1 9294 -N");
}
}

void sender_rauf_runter(Fl_Dial* v, void *) {
 
if (((Fl_Dial*) v)->value() < sender_prev) {
     sender_prev = (((Fl_Dial*) v)->value() );
     system("echo \"next\" | nc 127.0.0.1 9294 -N");
}

if (((Fl_Dial*) v)->value() > sender_prev) {
     sender_prev = (((Fl_Dial*) v)->value() );
     system("echo \"pref\" | nc 127.0.0.1 9294 -N");
}
}

static void CB_Hole_Info(void *data) {         // Timer callback
   printf("Timer! %d\n", ++count);            // Meldung bei jedem Timer tick
   char Text_4[30] = {("Timer! %d\n", count)};
   //Compilermeldung:
   //warning: narrowing conversion of '((void)0, count)' from 'int' to 'char' inside { } [-Wnarrowing]
   // char Text_4[30] = {("Timer! %d\n", count)};
   memcpy(Text_1, Text_4, sizeof(Text_4));
   zeile_1->value(Text_1);
   if ( count >= 5) {
       // Nach count Timer ticks, Timer ausschalten
       Fl::remove_timeout(CB_Hole_Info, data);
       printf("Timer ausgeschaltet.\n");
       memcpy(Text_1, Text_3, sizeof(Text_3));
       zeile_1->value(Text_1);
       zeile_2->value("jetzt gehts mit Button weiter");
   } else {
       // weniger als count Timer ticks? weiter machen
       Fl::repeat_timeout(2, CB_Hole_Info, data);
   }
}

int main(int argc, char **argv) {

Fl_Window *window = new Fl_Window(480,290,"iRadio");

zeile_1= new Fl_Output(80, 50, 295, 28);
zeile_1->value(Text_1); // Fl_Output* Zeile oben
zeile_2= new Fl_Output(80, 78, 295, 28);
zeile_2->value(Text_10); // Fl_Output* Zeile unten


Fl_Button *new_text = new Fl_Button(0, 250, 70 , 65, "@Text");

 Fl_Dial *vol_dial;
{ vol_dial = new Fl_Dial(285, 150, 90, 90, "- Volume +");
 vol_dial->box(FL_OSHADOW_BOX);
 vol_dial->color(FL_LIGHT2);
 vol_dial->labeltype(FL_ENGRAVED_LABEL);
 vol_dial->labelfont(12);
 vol_dial->labelcolor((Fl_Color)17);
 vol_dial->maximum(100);
 vol_dial->step(1);
 vol_dial->value(20);
} // Fl_Dial* vol_dial

Fl_Roller* sender;
{ sender = new Fl_Roller(80, 150, 140, 90, "Sender");
 sender->box(FL_EMBOSSED_BOX);
 sender->color(FL_LIGHT2);
 sender->labeltype(FL_ENGRAVED_LABEL);
 sender->labelcolor((Fl_Color)17);
 sender->minimum(1);
 sender->maximum(20);
 sender->step(1);
 sender->value(1);
} // Fl_Roller* o

vol_dial->callback( (Fl_Callback*) lauter_leiser);
sender->callback( (Fl_Callback*) sender_rauf_runter);
new_text->callback(anz_auffrischen, 0);
Fl::add_timeout(2, CB_Hole_Info);        // setup a timer

window->end();
window->show(argc, argv);
return Fl::run();
}

Beispielsweise bei der gemeinsamen Ausgabe von Texten und Zahlen (int count) ins Ausgabefenster:
char Text_4[30] = {("Timer! %d\n", count)};
Mit itoa wollte ich erst gar nicht anfangen, da es nicht zum C++ Standard gehört.

Des weiteren bereitet mir die Umsetzung von File *text_now_playing  z. B. in String Probleme.
Es funktionieren weder cout <<text_now_playing..... noch memcpy o. ä.

Die meisten Beispiele in der Fltk Hilfe arbeiten mit reinen Texten, in der Art:
zeile_1->value("Text_1");
Wenn aber im Programm Variablen benutzt werden, muss das passende Format für den Funktionsaufruf zu Verfügung gestellt werden
char const* Anzeige_1 = Text_1;
Da gibt es doch sicherlich einen Trick..

Es wäre sehr hilfreich, Bernhard, wenn Du mir ein wenig auf die Sprünge helfen könntest.
Grüße aus Wassenberg,
Norbert.
Zitieren
#50
Hallo zusammen,

mein Problem war ja gestern Abend das Abfangen der Antworten, welche vom vlc zurückkommen.

Da ich die Antworten von vlc zur Weiterverarbeitung haben möchte, kann ich diese ja in eine Datei umleiten, also z.B. mit dem Aufruf './Test_3 2> Antwort'.
'Test_3' ist der Name meines Programms.
Bei diesem Aufruf wird aber bei jedem Tastendruck eine Antwort geschrieben, was auf Dauer der Haltbarkeit der SD-Karte nicht zuträglich ist, gleichzeitig wird dadurch die erzeugte Datei immer länger.

Nun werde ich mir mittels des tmpfs-Dateisystems eine RAM-Disk einrichten, Größe 1% des Arbeitsspeichers.
Das sollte ausreichend sein.
Ich hoffe, dass das tmpf-Dateisystem auch auf dem Raspi funktioniert, ich habe es bisher nur auf meinem Laptop getestet.

Um mir das spätere auslesen der mich interessierenden Informationen (z.B. momentane Lautstärke) zu vereinfachen, werde ich vor jeder Anforderung mich interessierender Antworten die erzeugte Datei löschen.

Da ja nach jedem Rechnerneustart die Ramdisk weg ist, habe ich mir heute mein erstes Script erstellt, welches die Installation der Ramdisk erledigt und auch gleich mein Progrämmchen startet.

So langsam fängt die Sache an, richtig Spaß zu machen Smiley53 


Grüße

Martin
Zitieren
#51
(11.11.2018, 21:38)norbert_w schrieb: Hallo Bernhard und Mitleser,

ich habe ein wenig weiter programmiert und z.B. einen Timer eingebunden.
Aber so langsam stoße ich an meine Grenzen....

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <iostream>

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Text_Display.H>
#include <FL/Fl_Button.H>

#include <FL/Fl_Group.H>
#include <FL/Fl_Dial.H>
#include <FL/Fl_Roller.H>
#include <FL/Fl_Output.H>
#include <FL/fl_draw.H>
#include <FL/Enumerations.H>
#include <FL/Fl_Widget.H>
using namespace std;

Fl_Output* zeile_1;
Fl_Output* zeile_2;

//static int count = 0;
int sender_prev, volume_prev;
int count = 0;
char Text_1 [30] = "Taste drücken";
char Text_2 [30] = "L ä u f t";
char Text_3 [30] = "F e r t i g";

char Text_10 [30] = "weiss noch nicht...";

char const* Anzeige_1 = Text_1;
char const* Anzeige_2 = Text_10;

void anz_auffrischen(Fl_Widget *, void *) {
string text_stream;     
//system("echo \"prev\" | nc 127.0.0.1 9294 -N");
FILE *text_now_playing = popen("echo \"info\" | nc 127.0.0.1 9294 -N | grep now_playing:", "r");
pclose(text_now_playing);
//ab hier ??? was tun
}

void lauter_leiser(Fl_Dial* v, void *) {
 
if (((Fl_Dial*) v)->value() < volume_prev) {
     volume_prev = (((Fl_Dial*) v)->value() );
     system("echo \"voldown 1\" | nc 127.0.0.1 9294 -N");
}

if (((Fl_Dial*) v)->value() > volume_prev) {
     volume_prev = (((Fl_Dial*) v)->value() );
     system("echo \"volup 1\" | nc 127.0.0.1 9294 -N");
}
}

void sender_rauf_runter(Fl_Dial* v, void *) {
 
if (((Fl_Dial*) v)->value() < sender_prev) {
     sender_prev = (((Fl_Dial*) v)->value() );
     system("echo \"next\" | nc 127.0.0.1 9294 -N");
}

if (((Fl_Dial*) v)->value() > sender_prev) {
     sender_prev = (((Fl_Dial*) v)->value() );
     system("echo \"pref\" | nc 127.0.0.1 9294 -N");
}
}

static void CB_Hole_Info(void *data) {         // Timer callback
   printf("Timer! %d\n", ++count);            // Meldung bei jedem Timer tick
   char Text_4[30] = {("Timer! %d\n", count)};
   //Compilermeldung:
   //warning: narrowing conversion of '((void)0, count)' from 'int' to 'char' inside { } [-Wnarrowing]
   // char Text_4[30] = {("Timer! %d\n", count)};
   memcpy(Text_1, Text_4, sizeof(Text_4));
   zeile_1->value(Text_1);
   if ( count >= 5) {
       // Nach count Timer ticks, Timer ausschalten
       Fl::remove_timeout(CB_Hole_Info, data);
       printf("Timer ausgeschaltet.\n");
       memcpy(Text_1, Text_3, sizeof(Text_3));
       zeile_1->value(Text_1);
       zeile_2->value("jetzt gehts mit Button weiter");
   } else {
       // weniger als count Timer ticks? weiter machen
       Fl::repeat_timeout(2, CB_Hole_Info, data);
   }
}

int main(int argc, char **argv) {

Fl_Window *window = new Fl_Window(480,290,"iRadio");

zeile_1= new Fl_Output(80, 50, 295, 28);
zeile_1->value(Text_1); // Fl_Output* Zeile oben
zeile_2= new Fl_Output(80, 78, 295, 28);
zeile_2->value(Text_10); // Fl_Output* Zeile unten


Fl_Button *new_text = new Fl_Button(0, 250, 70 , 65, "@Text");

 Fl_Dial *vol_dial;
{ vol_dial = new Fl_Dial(285, 150, 90, 90, "- Volume +");
 vol_dial->box(FL_OSHADOW_BOX);
 vol_dial->color(FL_LIGHT2);
 vol_dial->labeltype(FL_ENGRAVED_LABEL);
 vol_dial->labelfont(12);
 vol_dial->labelcolor((Fl_Color)17);
 vol_dial->maximum(100);
 vol_dial->step(1);
 vol_dial->value(20);
} // Fl_Dial* vol_dial

Fl_Roller* sender;
{ sender = new Fl_Roller(80, 150, 140, 90, "Sender");
 sender->box(FL_EMBOSSED_BOX);
 sender->color(FL_LIGHT2);
 sender->labeltype(FL_ENGRAVED_LABEL);
 sender->labelcolor((Fl_Color)17);
 sender->minimum(1);
 sender->maximum(20);
 sender->step(1);
 sender->value(1);
} // Fl_Roller* o

vol_dial->callback( (Fl_Callback*) lauter_leiser);
sender->callback( (Fl_Callback*) sender_rauf_runter);
new_text->callback(anz_auffrischen, 0);
Fl::add_timeout(2, CB_Hole_Info);        // setup a timer

window->end();
window->show(argc, argv);
return Fl::run();
}

Beispielsweise bei der gemeinsamen Ausgabe von Texten und Zahlen (int count) ins Ausgabefenster:
char Text_4[30] = {("Timer! %d\n", count)};
Mit itoa wollte ich erst gar nicht anfangen, da es nicht zum C++ Standard gehört.

Des weiteren bereitet mir die Umsetzung von File *text_now_playing  z. B. in String Probleme.
Es funktionieren weder cout <<text_now_playing..... noch memcpy o. ä.

Die meisten Beispiele in der Fltk Hilfe arbeiten mit reinen Texten, in der Art:
zeile_1->value("Text_1");
Wenn aber im Programm Variablen benutzt werden, muss das passende Format für den Funktionsaufruf zu Verfügung gestellt werden
char const* Anzeige_1 = Text_1;
Da gibt es doch sicherlich einen Trick..

Es wäre sehr hilfreich, Bernhard, wenn Du mir ein wenig auf die Sprünge helfen könntest.


Hallo Norbert, 

dein Programm ist sehr verwirrend für mich! Was sollen die vielen globalen Variablen und Objekte? Einige Funktionen sind gar fragwürdig, warum werden in der Timer Callback ticks gezählt und der Timer dann deaktiviert? Sollen nicht dauerhaft die Anzeigen aktualisiert werden? Nun gut. Ich habe dein Programm mal etwas eingekürzt und verändert, aber doch grob deinen Stil belassen. Jetzt sollte theoretisch in der obersten Zeile alle zwei Sekunden der Sendername geholt und angezeigt werden. Vielleicht reicht das schon als "Sprung" für weitere Ideen. Die Struktur der Callbacks ist in FLTK ja weitestgehend frei definierbar, davon würde ich regen Gebrauch machen. Also weniger globale Sachen und mehr per Übergabe arbeiten.

Hier der abgeänderte Code:

Zitat:#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <iostream>

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Text_Display.H>
#include <FL/Fl_Button.H>

#include <FL/Fl_Group.H>
#include <FL/Fl_Dial.H>
#include <FL/Fl_Roller.H>
#include <FL/Fl_Output.H>
#include <FL/fl_draw.H>
#include <FL/Enumerations.H>
#include <FL/Fl_Widget.H>
using namespace std;

int sender_prev, volume_prev;
int count = 0;


void lauter_leiser(Fl_Dial* v, void *) {

if (((Fl_Dial*) v)->value() < volume_prev) {
     volume_prev = (((Fl_Dial*) v)->value() );
     system("echo \"voldown 1\" | nc 127.0.0.1 9294 -N");
}

if (((Fl_Dial*) v)->value() > volume_prev) {
     volume_prev = (((Fl_Dial*) v)->value() );
     system("echo \"volup 1\" | nc 127.0.0.1 9294 -N");
}
}

void sender_rauf_runter(Fl_Dial* v, void *) {

if (((Fl_Dial*) v)->value() < sender_prev) {
     sender_prev = (((Fl_Dial*) v)->value() );
     system("echo \"next\" | nc 127.0.0.1 9294 -N");
}

if (((Fl_Dial*) v)->value() > sender_prev) {
     sender_prev = (((Fl_Dial*) v)->value() );
     system("echo \"pref\" | nc 127.0.0.1 9294 -N");
}
}

void rmSubstr(char *str, const char *toRemove)
{
    size_t length = strlen(toRemove);
    while((str = strstr(str, toRemove)))
    {
        memmove(str, str + length, 1 + strlen(str + length));
    }
}

static void CB_Hole_Info(void *data) {         // Timer callback
  char now[64];
  FILE *text = popen("echo \"info\" | nc 127.0.0.1 9294 -N | grep title:", "r");
  Fl_Output *out = (Fl_Output*) data;

  fgets(now,64,text);
  rmSubstr(now,"| title:");
  rmSubstr(now,"\r");

  out->value(now);

  pclose(text);

  Fl::repeat_timeout(2,CB_Hole_Info, data);
}

int main(int argc, char **argv) {

Fl_Window *window = new Fl_Window(480,290,"iRadio");

Fl_Output* zeile_1;
Fl_Output* zeile_2;

zeile_1= new Fl_Output(80, 50, 295, 28);
zeile_2= new Fl_Output(80, 78, 295, 28);


Fl_Button *new_text = new Fl_Button(0, 250, 70 , 65, "@Text");

 Fl_Dial *vol_dial;
{ vol_dial = new Fl_Dial(285, 150, 90, 90, "- Volume +");
 vol_dial->box(FL_OSHADOW_BOX);
 vol_dial->color(FL_LIGHT2);
 vol_dial->labeltype(FL_ENGRAVED_LABEL);
 vol_dial->labelfont(12);
 vol_dial->labelcolor((Fl_Color)17);
 vol_dial->maximum(100);
 vol_dial->step(1);
 vol_dial->value(20);
} // Fl_Dial* vol_dial

Fl_Roller* sender;
{ sender = new Fl_Roller(80, 150, 140, 90, "Sender");
 sender->box(FL_EMBOSSED_BOX);
 sender->color(FL_LIGHT2);
 sender->labeltype(FL_ENGRAVED_LABEL);
 sender->labelcolor((Fl_Color)17);
 sender->minimum(1);
 sender->maximum(20);
 sender->step(1);
 sender->value(1);
} // Fl_Roller* o

vol_dial->callback( (Fl_Callback*) lauter_leiser);
sender->callback( (Fl_Callback*) sender_rauf_runter);
Fl::add_timeout(2, CB_Hole_Info, zeile_1);        // setup a timer

window->end();
window->show(argc, argv);
return Fl::run();
}


Gruß Bernhard
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung. 
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")
Zitieren
#52
(11.11.2018, 22:43)Radiobastler schrieb: Hallo zusammen,

mein Problem war ja gestern Abend das Abfangen der Antworten, welche vom vlc zurückkommen.

Da ich die Antworten von vlc zur Weiterverarbeitung haben möchte, kann ich diese ja in eine Datei umleiten, also z.B. mit dem Aufruf './Test_3 2> Antwort'.

Oh jetzt kommen Dateien ins Spiel. Sicher nicht eine der naheliegensten Lösungen des Problems, aber ich bin gespannt wie du es lösen willst. Mache mal weiter...

(11.11.2018, 22:43)Radiobastler schrieb: Bei diesem Aufruf wird aber bei jedem Tastendruck eine Antwort geschrieben, was auf Dauer der Haltbarkeit der SD-Karte nicht zuträglich ist, gleichzeitig wird dadurch die erzeugte Datei immer länger.

Überlege mal wie oft Du da eine Taste drücken müstest bis der Flashspeicher nicht mehr will. Ich denke vorher wirst Du einige Tastaturen verschleißen bis das Dateisystem nicht mehr will. Hast Du mal an die Lebenserwartung eines Hardwaretasters in einem Radio gedacht? Dein Flash ist da um mehrere 10er Faktoren robuster. Zudem werden Schreiboperationen über den ganzen Flash verteilt. Du wirst also selten die gleiche Speicherzelle nochmal treffen.

Wieso wird die Datei immer länger? Wird denn wirklich ein append gemacht? Nein!

(11.11.2018, 22:43)Radiobastler schrieb: Nun werde ich mir mittels des tmpfs-Dateisystems eine RAM-Disk einrichten, Größe 1% des Arbeitsspeichers.
Die Lösung wird immer komplexer ...., aber mache weiter.

(11.11.2018, 22:43)Radiobastler schrieb: So langsam fängt die Sache an, richtig Spaß zu machen Smiley53 

Wenigstens Einem. Bei dem was Du vorhast würde ich eher den Spaß verlieren. ;-) Überlege nochmal ob es nicht bessere Methoden gibt. Wie machen das nur die ganzen anderen Linux-Systementwickler bei Konsolenprogrammen? Es gibt ja viele ncurses-Programme die das gleiche Problem hätten, das bekannteste wäre der MidnightCommander "mc". Wie refreshen diese Programme immer wieder Ihre Oberflächen? Vielleicht findest Du mit Google ja noch bessere Lösungswege, oder halt in den manpages des Systems oder eines der genannten Bücher. Auch Webtutorials über ncurses gibt es viele die auf dein Problem eingehen.

Aber ich bin gespannt wohin dein Lösungsansatz (einfach oder komplex) letztendlich geht und welche Probleme noch umschifft werden müssen.

Mache weiter!
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung. 
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")
Zitieren
#53
Hallo Bernhard,
Zitat
Was sollen die vielen globalen Variablen und Objekte? Einige Funktionen sind gar fragwürdig, warum werden in der Timer Callback ticks gezählt und der Timer dann deaktiviert? Sollen nicht dauerhaft die Anzeigen aktualisiert werden?
Zitat Ende
Ich habe halt eine Menge probiert und den Code nicht bereinigt, bevor ich ihn schickte, sorry.


Bernhard, danke für Deine Unterstützung! Du hast mir sehr geholfen.
Ich werde mich melden.
Grüße aus Wassenberg,
Norbert.
Zitieren
#54
Hallo Norbert. Das war nicht böse gemeint, ich habe den Code nur nicht durchblickt weil sich da wohl mehrere Funktionen um die Aktualisierung der Ausgabezeilen gekloppt haben und auch außerhalb direkt drauf geschrieben wurde. Ich hoffe ich habe durch das einkürzen des Codes nicht eine für Dich wichtige Funktion gelöscht, aber ich denke wenn man nur eine Displayfunktion hat, dann bleibt der Code bei weiterem Ausbau übersichtlicher als wenn man für jedes einzelne Metadatenelement (Songtitel, Artist, Bitrate, ...) getrennte CallBacks macht. Du kannst der einen Timerfunktion ja noch beliebig weitere Zeiger und Zeigertypen übergeben. Bei void* must Du nur aufpassen das Du richtig Zurückcastest.

Gruß Bernhard.
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung. 
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")
Zitieren
#55
Hallo Bernhard,

habe Deine Bemerkung nicht als böse empfunden - Du hattest doch Recht, und der Ton passte schon.
Ich habe halt viel probiert um Möglichkeiten mit Timer- und Display-Funktionen zu begreifen.
Weisst Du Bernhard, vor 2 Wochen wusste ich nicht einmal was Fltk ist.
Grüße aus Wassenberg,
Norbert.
Zitieren
#56
Hallo Martin, 

ich hoffe ich habe mit meinen Post zu deinen sehr komplizierten Lösungvorhaben jetzt nicht die große Verwirrung bei Dir ausgelöst!?

Im Prinzip hat dein Programm lediglich ein Problem. Es wird nie die Möglichkeit des Neuzeichnens der GUI genutzt! Organisiere das Programm einfach etwas anders, sodaß
es die Möglichkeit hat auf die "Zerstörung" des Fensters zu reagieren. 

Dann läuft das ganz ohne Operationen in einem (RAM-) Dateisystem und die Überschreibungen werden nicht sichtbar!


.jpg   martin_gui.jpg (Größe: 24,88 KB / Downloads: 365)

Läuft dann (mit einer eventbasierten Aktualisierung der GUI) hier schon sehr gut und ressourcensparend und nichts wird mehr überschrieben!

Das Abändern des Netcat-Aufrufs  und Umleitung der Ausgabe ginge auch, aber bitte dann nicht ins Dateisystem umleiten! Deine GUI braucht sowieso die Möglichkeit des Neuzeichnens, also löse es besser gleich mit Bordmitteln von ncurses und in C/C++.

Ich schicke Dir mal anhand deines weiter oben geposteten Codegerüsts per PN eine Modifikation, die Dir vielleicht auf die Sprünge hilft.
So kommst Du vielleicht schneller zu einem funktionierenden Programm.

Gruß 
Bernhard
Ansprechpartner für Umbau oder Modernisierung von Röhrenradios mittels SDR,DAB+,Internetradio,Firmwareentwicklung. 
Unser Open-Source Softwarebaukasten für Internetradios gibt es auf der Github-Seite! Projekt: BM45/iRadio (Google "github BM45/iRadio")
Zitieren
#57
(10.11.2018, 21:48)Radiobastler schrieb: Hallo zusammen,

heute Abend habe ich mir das Internetradio nach der Anleitung bzw. dem Installationstool von Bernhard installiert.

Ebenso habe ich mir mein Textfrontend auf dem raspi neu compiliert.

Es läuft auch:


Aber sobald ich eine Taste drücke, passiert dies:



Gestartet habe ich das Progrämmchen im Verzeichnis /home/iRadio/

Weiterhin ist mir aufgefallen, dass nach einem reboot vlc nicht immer startet Huh 


Grüße

Martin

Hallo Martin. Ich habe mich in FLTK jetzt eingelesen und habe mir dein ncurses Programm von oben angeschaut. Mache es so wie Bernhard gesagt hat. Es fehlt eine Methode zum Neuzeichnen. FLTK und andere LIbs machen das auch so. Ich habe dein Programm mal provisorisch umgeschrieben das geht aber bestimmt eleganter.

Zitat:/* Frontend V3 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <curses.h>

void zeichne_neu() {
 initscr ();
 start_color();
 init_pair(1,COLOR_YELLOW,COLOR_BLUE);
 init_pair(2,COLOR_GREEN,COLOR_BLUE);
 init_pair(3,COLOR_RED,COLOR_BLUE);
 init_pair(4,COLOR_CYAN,COLOR_BLUE);
 attrset(A_BOLD|COLOR_PAIR(2));
 keypad (stdscr, TRUE);
 noecho();
 //Bildschirm füllen
 int Zeile, Spalte;
 for( Zeile = 0; Zeile < 26; Zeile++ )
 {
   for( Spalte = 0; Spalte < 81; Spalte++ )
   {
   mvprintw(Zeile,Spalte," ");
   }
 }
 mvprintw(2,15,"Textbasiertes Frontend für Internetradio");
 attrset(A_BOLD|COLOR_PAIR(3));
 mvprintw(5,10,"q:");
 attrset(A_BOLD|COLOR_PAIR(1));
 mvprintw(5,13,"Beenden");
 attrset(A_BOLD|COLOR_PAIR(3));
 mvprintw(7,10,"+:");
 attrset(A_BOLD|COLOR_PAIR(1));
 mvprintw(7,13,"Lauter");
 attrset(A_BOLD|COLOR_PAIR(3));
 mvprintw(9,10,"-:");
 attrset(A_BOLD|COLOR_PAIR(1));
 mvprintw(9,13,"Leiser");
 attrset(A_BOLD|COLOR_PAIR(3));
 mvprintw(11,10,"N:");
 attrset(A_BOLD|COLOR_PAIR(1));
 mvprintw(11,13,"Nächster Sender");
 attrset(A_BOLD|COLOR_PAIR(3));
 mvprintw(13,10,"V:");
 attrset(A_BOLD|COLOR_PAIR(1));
 mvprintw(13,13,"Vorheriger Sender");
 attrset(A_BOLD|COLOR_PAIR(3));
 mvprintw(15,10,"P:");
 attrset(A_BOLD|COLOR_PAIR(1));
 mvprintw(15,13,"Pause");
 attrset(A_BOLD|COLOR_PAIR(4));
 endwin();
}



int main (void) {
 int c;
  
 zeichne_neu();
 while ((c = getch ()) != 'q') {
   switch © {
   case 'v':
   case 'V':
     mvprintw (20,10,"                                        ");
     mvprintw (20,10,"Gewählte Funktion: Vorheriger Sender");
     system("echo \"prev\" | nc 127.0.0.1 9294 -N");
     zeichne_neu();
     break;
   case 'N':
   case 'n':
     mvprintw (20,10,"                                        ");
     mvprintw (20,10,"Gewählte Funktion: Nächster Sender");
     system("echo \"next\" | nc 127.0.0.1 9294 -N");  
     zeichne_neu();
     break;
   case '+':
     mvprintw (20,10,"                                         ");
     mvprintw (20,10,"Gewählte Funktion: Lauter");
     system("echo \"volup 2\" | nc 127.0.0.1 9294 -N ");
     zeichne_neu();
     break;
   case '-':
     mvprintw (20,10,"                                         ");
     mvprintw (20,10,"Gewählte Funktion: Leiser");
     system("echo \"voldown 2\" | nc 127.0.0.1 9294 -N");
     zeichne_neu();
     break;
   case 'P':
   case 'p':
     mvprintw (20,10,"                                         ");
     mvprintw (20,10,"Gewählte Funktion: Pause");
     //Hier folgt Funktionsaufruf 'Pause'
     zeichne_neu();
     break;
   }
 }
 endwin ();
 return 0;
}

Jetzt wird es bei jedem Tastendruck neu gezeichnet und die Ausgabe bleibt heil.
Bei ncurses kann man auch ein in ein virtuelles Fenster zeichnen und dann irgendwann zur Laufzeit nach vorne schieben. Die Technik nennt sich wohle Pageflipping. So tief stecke ich da aber nicht drin. Es geht jedenfalls ohne Umleitung in eine Datei. Mit der Codezeile  FILE *text = popen("echo \"info\" | nc 127.0.0.1 9294 -N | grep title:", "r");
bekommst Du auch die Senderinformationen in das C Programm eingelesen ohne eine Datei langsam erst öffnen zu müssen.


Otto.


Angehängte Dateien Thumbnail(s)
   
Zitieren
#58
Hallo zusammen,

vielen Dank allen, die mir auf die Sprünge geholfen haben!

Ich werde mich jetzt am kommenden Wochenende mit der 'popen'-Funktion näher beschäftigen, insbesondere damit, wie ich die gepufferten Informationen in mein kleines Menü bekomme.

Diese grafische Oberfläche sieht auch sehr interessant aus!
Damit werde ich mich zu gegebener Zeit auch mal auseinander setzen.
Jedenfalls ist das ein sehr vielversprechender Ansatz für ein 'Stand-alone'-Gerät.
Geeignete Touchpanels bekommt man ja mittlerweile wie den sprichwörtlichen Sand am Meer.


Viele Grüße

Martin
Zitieren
#59
Hallo zusammen,

heute Abend beim zusammenstellen einer Senderliste bin ich über diese Internetseite gestolpert: 
https://www.stream-urls.de/webradio

Leider veröffentlichen nicht alle Stationen ihre URL.


Grüße

Martin
Zitieren
#60
Hallo zusammen,

auf Anregung von Otto habe ich mein Steuerprogrämmchen neu aufgebaut, so dass es mir das Menü nicht mehr zerstört.

Wenn ich mir aber nun das 'popen'-Kommando einbaue, wie in Post #51 beschrieben, passiert sowas:

.png   Bildschirmfoto vom 2018-11-17 22-18-22.png (Größe: 10,12 KB / Downloads: 282)

das sieht aus wie seinerzeit bei einem seriellen Drucker mit falschen Baudrate Rolleyes

Hier der Code dazu:
   

Ich glaub', ich brauche noch einige Zeit bis ich mit C so richtig warm werde.


Grüße

Martin

der jetzt Smiley63 geht
Zitieren


Möglicherweise verwandte Themen…
Thema Verfasser Antworten Ansichten Letzter Beitrag
  Neue Erfahrungen mit FL2K und AM Stereo/Mono Semir 2 252 20.03.2024, 22:40
Letzter Beitrag: Semir
  Huth E72 Internetradio mit ESP32 saarfranzose 10 1.780 12.05.2023, 14:49
Letzter Beitrag: saarfranzose
  Ein Internetradio Bausatz von PIMORONI Bernhard45 200 81.526 06.06.2022, 19:17
Letzter Beitrag: Reparateur
  Stereo Decoder fuer alte Radios- Export radio-volker 4 1.395 08.03.2022, 19:30
Letzter Beitrag: radio-volker
  Dementia III ESP32 Internetradio mit Simulation saarfranzose 9 2.804 21.01.2022, 23:14
Letzter Beitrag: saarfranzose

Gehe zu: