Seite 1 von 1

midicat /dev/midi2

Verfasst: Mi Okt 29, 2014 1:28 pm
von ouroboros
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.

Re: midicat /dev/midi2

Verfasst: Mi Okt 29, 2014 2:22 pm
von oenone
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.

Re: midicat /dev/midi2

Verfasst: Mi Okt 29, 2014 3:16 pm
von ouroboros
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.

Re: midicat /dev/midi2

Verfasst: Mi Okt 29, 2014 4:01 pm
von Xin
printf ist gebuffert. Du kannst den Buffer flushen mit fflush( stdout ); oder den Buffer mit setbuff() abschalten.

Re: midicat /dev/midi2

Verfasst: Mi Okt 29, 2014 5:19 pm
von ouroboros
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.

Re: midicat /dev/midi2

Verfasst: Mi Okt 29, 2014 6:27 pm
von oenone
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.

Re: midicat /dev/midi2

Verfasst: Fr Okt 31, 2014 10:50 am
von ouroboros
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.

Re: midicat /dev/midi2

Verfasst: Fr Okt 31, 2014 11:19 am
von oenone
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

Re: midicat /dev/midi2

Verfasst: Fr Okt 31, 2014 1:41 pm
von Xin
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?

Re: midicat /dev/midi2

Verfasst: Sa Nov 01, 2014 5:55 pm
von oenone
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.