From: c vw Date: Fri, 14 May 2021 07:45:46 +0000 (+0200) Subject: Further MIDI fixes, mainly for LINUX. X-Git-Url: https://git.rkrishnan.org/listings/vdrive/index.php?a=commitdiff_plain;h=ca013c4c60496dd1633b0bceef809a482be5d17b;p=pihpsdr.git Further MIDI fixes, mainly for LINUX. --- diff --git a/alsa_midi.c b/alsa_midi.c index ab8a98b..c7ae59a 100644 --- a/alsa_midi.c +++ b/alsa_midi.c @@ -31,6 +31,14 @@ MIDI_DEVICE midi_devices[MAX_MIDI_DEVICES]; int n_midi_devices; +// +// The following must not reside in midi_devices since it +// needs special #includes +// +static pthread_t midi_thread_id[MAX_MIDI_DEVICES]; +static char *midi_port[MAX_MIDI_DEVICES]; +static snd_rawmidi_t *midi_input[MAX_MIDI_DEVICES]; + static void* midi_thread(void *); static enum { @@ -48,15 +56,16 @@ static enum { static gboolean configure=FALSE; -static snd_rawmidi_t *input; - void configure_midi_device(gboolean state) { configure=state; } static void *midi_thread(void *arg) { + int index = (int) arg; + snd_rawmidi_t *input=midi_input[index]; + char *port=midi_port[index]; + int ret; - MIDI_DEVICE *midi_device=(MIDI_DEVICE *)arg; int npfds; struct pollfd *pfds; unsigned char buf[32]; @@ -64,20 +73,15 @@ static void *midi_thread(void *arg) { unsigned short revents; int i; int chan,arg1,arg2; - snd_rawmidi_t *input; - - 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 */ + + npfds = snd_rawmidi_poll_descriptors_count(input); pfds = alloca(npfds * sizeof(struct pollfd)); snd_rawmidi_poll_descriptors(input, pfds, npfds); for (;;) { ret = poll(pfds, npfds, 250); - if (!midi_device->active) break; + if (!midi_devices[index].active) break; if (ret < 0) { fprintf(stderr,"poll failed: %s\n", strerror(errno)); // Do not give up, but also do not fire too rapidly @@ -92,9 +96,10 @@ static void *midi_thread(void *arg) { if (!(revents & POLLIN)) continue; // something has arrived ret = snd_rawmidi_read(input, buf, 64); + g_print("%s: raw read returned %d\n", __FUNCTION__,ret); if (ret == 0) continue; if (ret < 0) { - fprintf(stderr,"cannot read from port \"%s\": %s\n", midi_device->port, snd_strerror(ret)); + fprintf(stderr,"cannot read from port \"%s\": %s\n", port, snd_strerror(ret)); continue; } // process bytes in buffer. Since they no not necessarily form complete messages @@ -182,32 +187,61 @@ static void *midi_thread(void *arg) { } } } - // 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)); - } + return NULL; } -int register_midi_device(int index) { +void register_midi_device(int index) { int i; int ret=0; - pthread_t midi_thread_id; - if (index < 0 || index > MAX_MIDI_DEVICES) return -1;; + if (index < 0 || index > MAX_MIDI_DEVICES) return; + + g_print("%s: open MIDI device %d\n", __FUNCTION__, index); - ret = pthread_create(&midi_thread_id, NULL, midi_thread, &midi_devices[index]); + if ((ret = snd_rawmidi_open(&midi_input[index], NULL, midi_port[index], SND_RAWMIDI_NONBLOCK)) < 0) { + fprintf(stderr,"cannot open port \"%s\": %s\n", midi_port[index], snd_strerror(ret)); + return; + } + snd_rawmidi_read(midi_input[index], NULL, 0); /* trigger reading */ + + + ret = pthread_create(&midi_thead_id[index], NULL, midi_thread, (void *) index); if (ret < 0) { g_print("%s: Failed to create MIDI read thread\n",__FUNCTION__); - return -1; + if((ret = snd_rawmidi_close(midi_input[index])) < 0) { + g_print("%s: cannot close port: %s\n",__FUNCTION__, snd_strerror(ret)); + } + return; } midi_devices[index].active=1; - return 0; + return; } void close_midi_device(int index) { - g_print("%s\n",__FUNCTION__); + int ret; + + if (index < 0 || index > MAX_MIDI_DEVICES) return; + if (midi_devices[index].active == 0) return; + + // + // Note that if this is called from get_midi_devices(), + // the port and device names do exist but may be wrong. + // + // Tell thread to stop + // midi_devices[index].active=0; - usleep(500000L); // make sure the reading thread has noticed + // + // wait for thread to complete + // + ret=pthread_join(midi_devices[index].midi_thread_id, NULL); + if (ret != 0) { + g_print("%s: cannot join: %s\n", __FUNCTION__, strerror(ret)); + } + // + // Close MIDI device + if((ret = snd_rawmidi_close(midi_input[index])) < 0) { + g_print("%s: cannot close port: %s\n",__FUNCTION__, snd_strerror(ret)); + } } void get_midi_devices() { @@ -276,17 +310,41 @@ void get_midi_devices() { devnam=subnam; } - if (midi_devices[n_midi_devices].name != NULL) { - g_free(midi_devices[n_midi_devices].name); + // + // If the name was already present at the same position, just keep + // it and do nothing. + // If the names do not match and the slot is occupied by a opened device, + // close it first + // + int match = 1; + if (midi_devices[n_midi_devices].name == NULL) { + midi_devices[n_midi_devices].name=g_new(gchar,strlen(devnam)+1); + match = 0; + } else { + if (strcmp(devnam, midi_devices[n_midi_devices].name) { + g_free(midi_devices[n_midi_devices].name); + midi_devices[n_midi_devices].name=g_new(gchar,strlen(devnam)+1); + match = 0; + } } - 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); + if (midi_port[n_midi_devices] == NULL) { + midi_port[n_midi_devices]=g_new(gchar,strlen(portname)+1); + match = 0; + } else { + if (strcmp(midi_port[n_midi_devices], portname) { + g_free(midi_port[n_midi_devices]); + midi_port[n_midi_devices]=g_new(gchar,strlen(portname)+1); + match = 0; + } + } + // + // Close MIDI device if it was open, except if the device is + // the same as before. In this case, just let the thread + // proceed + // + if (match == 0 && midi_index[n_midi_devices].active) { + close_midi_device(n_midi_devices); } - midi_devices[n_midi_devices].port=g_new(gchar,strlen(portname)+1); - strcpy(midi_devices[n_midi_devices].port,portname); n_midi_devices++; } } diff --git a/alsa_midi.h b/alsa_midi.h index 234a57e..2406b11 100644 --- a/alsa_midi.h +++ b/alsa_midi.h @@ -1,6 +1,5 @@ typedef struct _midi_device { char *name; - char *port; int active; } MIDI_DEVICE; diff --git a/midi_menu.c b/midi_menu.c index bf1ca98..9b0d273 100644 --- a/midi_menu.c +++ b/midi_menu.c @@ -129,14 +129,6 @@ static void cleanup() { } } -static gboolean wheelclose_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { - return TRUE; -} - -static gboolean wheeldelete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) { - return FALSE; -} - static gboolean close_cb (GtkWidget *widget, GdkEventButton *event, gpointer data) { cleanup(); return TRUE; @@ -350,7 +342,6 @@ static void wheelparam_cb(GtkWidget *widget, gpointer user_data) { int what = GPOINTER_TO_INT(user_data); int val=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget)); int newval=val; - g_print("WHEEL CB what=%d newval=%d\n", what, newval); if (thisType != MIDI_TYPE_WHEEL) { // we should never arrive here @@ -505,7 +496,6 @@ static void load_original_cb(GtkWidget *widget,gpointer user_data) { GTK_RESPONSE_ACCEPT, NULL); chooser = GTK_FILE_CHOOSER (load_dialog); - gtk_file_chooser_set_current_name(chooser,"midi.midi"); res = gtk_dialog_run (GTK_DIALOG (load_dialog)); if(res==GTK_RESPONSE_ACCEPT) { char *loadfilename=gtk_file_chooser_get_filename(chooser); @@ -1115,7 +1105,7 @@ void midi_menu(GtkWidget *parent) { set_fl2 = gtk_spin_button_new_with_range(-1.0, 127.0, 1.0); gtk_grid_attach(GTK_GRID(WheelGrid), set_fl2, col, row, 1, 1); - g_signal_connect(set_vfl2, "value-changed", G_CALLBACK(wheelparam_cb), GINT_TO_POINTER(5)); + g_signal_connect(set_fl2, "value-changed", G_CALLBACK(wheelparam_cb), GINT_TO_POINTER(5)); col++; row++;