midicat /dev/midi2

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
ouroboros
Beiträge: 5
Registriert: Mi Okt 29, 2014 11:25 am

midicat /dev/midi2

Beitrag von ouroboros » Mi Okt 29, 2014 1:28 pm

Hallo liebe Progger,
ich versuche mich gerade an einem kleinen Progrämmchen
mit dem gcc unter Linux.
Hier gibt es unter /dev ein Gerät, das sich als Datei behandeln läßt,
Namens "midi[Gerätenummer]", also z.B. "/dev/midi2" .
Mit ">cat /dev/midi2" spuckt mir die Kommandozeile brav die einfliegenden
Einzelbyte von einer angeschlossenen MIDI-Tastatur als Zeichen auf der Konsole aus.
Ich hätte nun aber gerne eine Konsolenausgabe als Dezimal- oder Hexwert,
zudem ist es für mich sicher eine gute Übung, diese "Rohwerte"
in einem C-Progrämmchen formatiert und interpretiert auf der Konsole auszugeben.
Das ist aber erstmal Zweitrangig und ich würde mich freuen,
wenn ich nach einem Programmaufruf, wie: ">midicat /dev/midi2" die einfliegenden
Byte als Dezimalwert zu Gesicht bekäme.
Erstmal dachte ich mir das so:

Code: Alles auswählen

#include <stdio.h>
#define uint8_t unsigned char
int main(int argc, char *argv[])
{
    printf("\n\n%s:\n",argv[0]);// Erstmal nur zum Jux
    uint8_t byte_in;
    FILE *fp =fopen("/dev/midi2","r");
    while(1)
    {
	fscanf(fp,"%c", &byte_in);
	printf("0x%x ",byte_in);
    }
    return 0;
}
Das geht zwar ohne Warnungen durch den gcc, aber machen tuts nix.
Ich nehme an, das bleibt am fscanf() hängen?
Naja, ich denke, man sieht wenigstens, was ich meine
und schonmal Dank fürs Gelesenhaben.

Benutzeravatar
oenone
Beiträge: 223
Registriert: Do Sep 01, 2011 2:42 pm
Wohnort: Bremen
Kontaktdaten:

Re: midicat /dev/midi2

Beitrag von oenone » Mi Okt 29, 2014 2:22 pm

Zuerst solltest du die Datei binär öffnen, also "rb" statt "r" in fopen(). Für byteweises Auslesen solltest du auch eher fgetc() statt fscanf benutzen.

ouroboros
Beiträge: 5
Registriert: Mi Okt 29, 2014 11:25 am

Re: midicat /dev/midi2

Beitrag von ouroboros » Mi Okt 29, 2014 3:16 pm

Vielen Dank, et läuft!

Code: Alles auswählen

include <stdio.h>
#define uint8_t unsigned char
int main(int argc, char *argv[])
{
    printf("\n\n%s:\n",argv[0]);// Erstmal nur zum Jux
    uint8_t byte_in;
    FILE *midi_in;
    midi_in =fopen("/dev/midi2","rb");
    while(1)
    {
        printf("\n");// Das muss sein, sonst bleibts hängen.
        byte_in=fgetc(midi_in);
        printf("0x%x",byte_in);
    }
    return 0;
}

Seltsamerweise muß ich aber in der Schleife mit printf() noch ein "\n" ausgeben, sonst bleibts hängen.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: midicat /dev/midi2

Beitrag von Xin » Mi Okt 29, 2014 4:01 pm

printf ist gebuffert. Du kannst den Buffer flushen mit fflush( stdout ); oder den Buffer mit setbuff() abschalten.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

ouroboros
Beiträge: 5
Registriert: Mi Okt 29, 2014 11:25 am

Re: midicat /dev/midi2

Beitrag von ouroboros » Mi Okt 29, 2014 5:19 pm

Nochn fettes Danke:
"setbuf(stdout,NULL);"
vor der Endlosschleife funktioniert prima.
Die Byte werden jetzt sofort ausgegeben.

Ich weiß, daß diese Etüde noch nicht schön aussieht:
Erstmal wird eine "Datei" geöffnet und nicht wieder zugemacht
und zweitens ist da ne Endlosschleife drin.

Benutzeravatar
oenone
Beiträge: 223
Registriert: Do Sep 01, 2011 2:42 pm
Wohnort: Bremen
Kontaktdaten:

Re: midicat /dev/midi2

Beitrag von oenone » Mi Okt 29, 2014 6:27 pm

ouroboros hat geschrieben:Ich weiß, daß diese Etüde noch nicht schön aussieht:
Erstmal wird eine "Datei" geöffnet und nicht wieder zugemacht
und zweitens ist da ne Endlosschleife drin.
Da du die Datei wegen der Endlosschleife nicht schließen kannst ist es egal, dass du kein fclose() benutzt. Der Filehandle wird eh vom Betriebssystem ausgegeben, sobald das Programm beendet wird.

Eine Endlosschleife ist auch nicht unbedingt ein no-go. Je nachdem was du damit machst.

ouroboros
Beiträge: 5
Registriert: Mi Okt 29, 2014 11:25 am

Re: midicat /dev/midi2

Beitrag von ouroboros » Fr Okt 31, 2014 10:50 am

oenone hat geschrieben:Eine Endlosschleife ist auch nicht unbedingt ein no-go. Je nachdem was du damit machst.
Besteht nicht die Möglichkeit, sowas wie nen Tastaturinterrupt zu definieren?
Ich habe schon ein bischen mit dem Avr-gcc die kleinen Atmel Microcontroller bearbeitet
und ich nehme an, hier verhält sich das ähnlich:
Das Programm bleibt eben am fgetc() hängen und wartet unbedingt aufs nächste MIDI-Byte.
[Strg] +[c] wird ja auch nur ein Interruptaufruf sein, nur schmeist einen das eben komplett aus dem Programm.

Benutzeravatar
oenone
Beiträge: 223
Registriert: Do Sep 01, 2011 2:42 pm
Wohnort: Bremen
Kontaktdaten:

Re: midicat /dev/midi2

Beitrag von oenone » Fr Okt 31, 2014 11:19 am

Ja, in C kannst du Strg-C mit Signals abfangen. Siehe hier:

http://man7.org/linux/man-pages/man2/sigaction.2.html

Oder weniger portabel mit signal(): http://www.proggen.org/doku.php?id=c:lib:signal:start

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8859
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: midicat /dev/midi2

Beitrag von Xin » Fr Okt 31, 2014 1:41 pm

oenone hat geschrieben:Ja, in C kannst du Strg-C mit Signals abfangen. Siehe hier:

http://man7.org/linux/man-pages/man2/sigaction.2.html

Oder weniger portabel mit signal(): http://www.proggen.org/doku.php?id=c:lib:signal:start
Weshalb ist signal() weniger portabel?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
oenone
Beiträge: 223
Registriert: Do Sep 01, 2011 2:42 pm
Wohnort: Bremen
Kontaktdaten:

Re: midicat /dev/midi2

Beitrag von oenone » Sa Nov 01, 2014 5:55 pm

Weil signal() sich je nach Unix-Variante und früher sogar je nach Linux-Distribution anders verhalten hat. Einzige das setzen von SIG_IGN oder SIG_DFL ist im Standard festgeschrieben und daher portabel. Mehr Infos findet man auf Linux in der Manpage zu signal(2):
http://man7.org/linux/man-pages/man2/signal.2.html

Multithreaded Prozesse sind auch unspezifiziert, da sollte man auch eher sigaction() benutzen.

Antworten