From 0f83c3a30f0dfeef8aacbdd03a74c19c1eb52b9f Mon Sep 17 00:00:00 2001 From: c vw Date: Mon, 10 May 2021 20:09:30 +0200 Subject: [PATCH] Applied "midimenu" changes to Linux case. --- alsa_midi.c | 188 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 121 insertions(+), 67 deletions(-) diff --git a/alsa_midi.c b/alsa_midi.c index bf12420..ab8a98b 100644 --- a/alsa_midi.c +++ b/alsa_midi.c @@ -18,14 +18,19 @@ * program amidi.c in alsautils. */ +#include #include "midi.h" +#include "midi_menu.h" +#include "alsa_midi.h" #ifndef __APPLE__ #include #include -static pthread_t midi_thread_id; +MIDI_DEVICE midi_devices[MAX_MIDI_DEVICES]; +int n_midi_devices; + static void* midi_thread(void *); static enum { @@ -41,9 +46,17 @@ static enum { CMD_PITCH, } command; -static void *midi_thread(void *data) { +static gboolean configure=FALSE; + +static snd_rawmidi_t *input; + +void configure_midi_device(gboolean state) { + configure=state; +} + +static void *midi_thread(void *arg) { int ret; - snd_rawmidi_t *input; + MIDI_DEVICE *midi_device=(MIDI_DEVICE *)arg; int npfds; struct pollfd *pfds; unsigned char buf[32]; @@ -51,11 +64,10 @@ static void *midi_thread(void *data) { unsigned short revents; int i; int chan,arg1,arg2; - char *portname = (char *) data; + snd_rawmidi_t *input; - if ((ret = snd_rawmidi_open(&input, NULL, portname, SND_RAWMIDI_NONBLOCK)) < 0) { - fprintf(stderr,"cannot open port \"%s\": %s\n", portname, snd_strerror(ret)); - free(portname); + if ((ret = snd_rawmidi_open(&input, NULL, midi_device->port, SND_RAWMIDI_NONBLOCK)) < 0) { + fprintf(stderr,"cannot open port \"%s\": %s\n", midi_device->port, snd_strerror(ret)); return NULL; } snd_rawmidi_read(input, NULL, 0); /* trigger reading */ @@ -65,6 +77,7 @@ static void *midi_thread(void *data) { snd_rawmidi_poll_descriptors(input, pfds, npfds); for (;;) { ret = poll(pfds, npfds, 250); + if (!midi_device->active) break; if (ret < 0) { fprintf(stderr,"poll failed: %s\n", strerror(errno)); // Do not give up, but also do not fire too rapidly @@ -81,7 +94,7 @@ static void *midi_thread(void *data) { ret = snd_rawmidi_read(input, buf, 64); if (ret == 0) continue; if (ret < 0) { - fprintf(stderr,"cannot read from port \"%s\": %s\n", portname, snd_strerror(ret)); + fprintf(stderr,"cannot read from port \"%s\": %s\n", midi_device->port, snd_strerror(ret)); continue; } // process bytes in buffer. Since they no not necessarily form complete messages @@ -129,19 +142,39 @@ static void *midi_thread(void *data) { // messages with velocity == 0 when releasing // a push-button if (arg2 == 0) { - NewMidiEvent(MIDI_EVENT_NOTE, chan, arg1, 0); + if(configure) { + NewMidiConfigureEvent(MIDI_EVENT_NOTE, chan, arg1, 0); + } else { + NewMidiEvent(MIDI_EVENT_NOTE, chan, arg1, 0); + } } else { - NewMidiEvent(MIDI_EVENT_NOTE, chan, arg1, 1); + if(configure) { + NewMidiConfigureEvent(MIDI_EVENT_NOTE, chan, arg1, 1); + } else { + NewMidiEvent(MIDI_EVENT_NOTE, chan, arg1, 1); + } } break; case CMD_NOTEOFF: - NewMidiEvent(MIDI_EVENT_NOTE, chan, arg1, 0); + if(configure) { + NewMidiConfigureEvent(MIDI_EVENT_NOTE, chan, arg1, 0); + } else { + NewMidiEvent(MIDI_EVENT_NOTE, chan, arg1, 0); + } break; case CMD_CTRL: - NewMidiEvent(MIDI_EVENT_CTRL, chan, arg1, arg2); + if(configure) { + NewMidiConfigureEvent(MIDI_EVENT_CTRL, chan, arg1, arg2); + } else { + NewMidiEvent(MIDI_EVENT_CTRL, chan, arg1, arg2); + } break; case CMD_PITCH: - NewMidiEvent(MIDI_EVENT_PITCH, chan, 0, arg1+128*arg2); + if(configure) { + NewMidiConfigureEvent(MIDI_EVENT_PITCH, chan, 0, arg1+128*arg2); + } else { + NewMidiEvent(MIDI_EVENT_PITCH, chan, 0, arg1+128*arg2); + } break; } state=STATE_SKIP; @@ -149,42 +182,67 @@ static void *midi_thread(void *data) { } } } + // no longer active: close and quit + if((ret = snd_rawmidi_close(input)) < 0) { + g_print("%s: cannot close port: %s\n",__FUNCTION__, snd_strerror(ret)); + } +} + +int register_midi_device(int index) { + int i; + int ret=0; + pthread_t midi_thread_id; + + if (index < 0 || index > MAX_MIDI_DEVICES) return -1;; + + ret = pthread_create(&midi_thread_id, NULL, midi_thread, &midi_devices[index]); + if (ret < 0) { + g_print("%s: Failed to create MIDI read thread\n",__FUNCTION__); + return -1; + } + midi_devices[index].active=1; + return 0; +} + +void close_midi_device(int index) { + g_print("%s\n",__FUNCTION__); + midi_devices[index].active=0; + usleep(500000L); // make sure the reading thread has noticed } -void register_midi_device(char *myname) { +void get_midi_devices() { - int mylen=strlen(myname); snd_ctl_t *ctl; snd_rawmidi_info_t *info; int card, device, subs, sub, ret; const char *devnam, *subnam; int found=0; - char name[64]; - char *portname; + char portname[64]; + n_midi_devices=0; card=-1; if ((ret = snd_card_next(&card)) < 0) { fprintf(stderr,"cannot determine card number: %s\n", snd_strerror(ret)); return; } while (card >= 0) { - fprintf(stderr,"Found Sound Card=%d\n",card); - sprintf(name,"hw:%d", card); - if ((ret = snd_ctl_open(&ctl, name, 0)) < 0) { + //fprintf(stderr,"Found Sound Card=%d\n",card); + sprintf(portname,"hw:%d", card); + if ((ret = snd_ctl_open(&ctl, portname, 0)) < 0) { fprintf(stderr,"cannot open control for card %d: %s\n", card, snd_strerror(ret)); return; } - device = -1; - // loop through devices of the card - for (;;) { - if ((ret = snd_ctl_rawmidi_next_device(ctl, &device)) < 0) { + device = -1; + // loop through devices of the card + for (;;) { + if ((ret = snd_ctl_rawmidi_next_device(ctl, &device)) < 0) { fprintf(stderr,"cannot determine device number: %s\n", snd_strerror(ret)); break; } - if (device < 0) break; - fprintf(stderr,"Found Device=%d on Card=%d\n", device, card); - // found sub-device - snd_rawmidi_info_alloca(&info); + if (device < 0) break; + //fprintf(stderr,"Found Device=%d on Card=%d\n", device, card); + // found sub-device + snd_rawmidi_info_alloca(&info); snd_rawmidi_info_set_device(info, device); snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_INPUT); ret = snd_ctl_rawmidi_info(ctl, info); @@ -192,10 +250,10 @@ void register_midi_device(char *myname) { subs = snd_rawmidi_info_get_subdevices_count(info); } else { subs = 0; - } - fprintf(stderr,"Number of MIDI input devices: %d\n", subs); - if (!subs) break; - // subs: number of sub-devices to device on card + } + //fprintf(stderr,"Number of MIDI input devices: %d\n", subs); + if (!subs) break; + // subs: number of sub-devices to device on card for (sub = 0; sub < subs; ++sub) { snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_INPUT); snd_rawmidi_info_set_subdevice(info, sub); @@ -205,47 +263,43 @@ void register_midi_device(char *myname) { card, device, sub, snd_strerror(ret)); break; } - devnam = snd_rawmidi_info_get_name(info); - subnam = snd_rawmidi_info_get_subdevice_name(info); - if (!strncmp(myname, devnam, mylen)) { - found=1; - // free() portname at the end of midi_thread - portname=malloc(64); - // If there is only one sub-device and it has no name, we use - // devnam for comparison and make a portname of form "hw:x,y", - // else we use subnam for comparison and make a portname of form "hw:x,y,z". - if (sub == 0 && subnam[0] == '\0') { - sprintf(portname,"hw:%d,%d", card, device); - } else { - sprintf(portname,"hw:%d,%d,%d", card, device, sub); - devnam=subnam; - } - fprintf(stderr,"MIDI device >%s< selected (PortName=>%s<)\n", devnam, portname); - } else { - fprintf(stderr,"MIDI device >%s< not matching >%s<\n", devnam, myname); - } if (found) break; - } - if (found) break; - } - snd_ctl_close(ctl); - if (found) break; - // next card + devnam = snd_rawmidi_info_get_name(info); + subnam = snd_rawmidi_info_get_subdevice_name(info); + // If there is only one sub-device and it has no name, we use + // devnam for comparison and make a portname of form "hw:x,y", + // else we use subnam for comparison and make a portname of form "hw:x,y,z". + if (sub == 0 && subnam[0] == '\0') { + sprintf(portname,"hw:%d,%d", card, device); + } else { + sprintf(portname,"hw:%d,%d,%d", card, device, sub); + devnam=subnam; + } + + if (midi_devices[n_midi_devices].name != NULL) { + g_free(midi_devices[n_midi_devices].name); + } + midi_devices[n_midi_devices].name=g_new(gchar,strlen(devnam)+1); + strcpy(midi_devices[n_midi_devices].name,devnam); + + if (midi_devices[n_midi_devices].port != NULL) { + g_free(midi_devices[n_midi_devices].port); + } + midi_devices[n_midi_devices].port=g_new(gchar,strlen(portname)+1); + strcpy(midi_devices[n_midi_devices].port,portname); + n_midi_devices++; + } + } + snd_ctl_close(ctl); + // next card if ((ret = snd_card_next(&card)) < 0) { fprintf(stderr,"cannot determine card number: %s\n", snd_strerror(ret)); break; } } - if (!found) { - fprintf(stderr,"MIDI device %s NOT FOUND!\n", myname); - return; - } - // Found our MIDI input device. Spawn off a thread reading data - // (use the same variable midi_thread_id for all MIDI threads - // since it is not used again). - ret = pthread_create(&midi_thread_id, NULL, midi_thread, portname); - if (ret < 0) { - fprintf(stderr,"Failed to create MIDI read thread\n"); + + for(int i=0;i