]> git.rkrishnan.org Git - pihpsdr.git/commitdiff
Support for multiple MIDI devices (so far only MacOS)
authorc vw <dl1ycf@darc.de>
Thu, 6 May 2021 17:01:59 +0000 (19:01 +0200)
committerc vw <dl1ycf@darc.de>
Thu, 6 May 2021 17:01:59 +0000 (19:01 +0200)
alsa_midi.h
mac_midi.c
midi.h
midi2.c
midi_menu.c
midi_menu.h
new_menu.c
radio.c

index 02acc84b04bd436033d6e6a344a5bc4a468bd5e4..234a57ed09d20c3f44d9de2727549e7e5708786a 100644 (file)
@@ -1,6 +1,7 @@
 typedef struct _midi_device {
   char *name;
   char *port;
+  int  active;
 } MIDI_DEVICE;
 
 #define MAX_MIDI_DEVICES 10
@@ -9,4 +10,3 @@ extern MIDI_DEVICE midi_devices[MAX_MIDI_DEVICES];
 extern int n_midi_devices;
 
 extern void get_midi_devices();
-extern int register_midi_device(char *myname);
index 36570b5d40fca4ae3a1ec542a95bae8a28590fa3..fb45b29f30b3d5d11ccbb9c4bc5be2c5185178b5 100644 (file)
 #include "radio.h"
 #include "midi.h"
 #include "midi_menu.h"
+#include "alsa_midi.h"
 
 #ifdef __APPLE__
 
-typedef struct _midi_device {
-  char *name;
-  char *port;
-} MIDI_DEVICE;
-
-#define MAX_MIDI_DEVICES 10
-
-MIDI_DEVICE midi_devices[MAX_MIDI_DEVICES];
-int n_midi_devices;
-
-
 /*
  * For MacOS, things are easy:
  * The OS takes care of everything, we only have to register a callback
@@ -188,50 +178,43 @@ static void ReadMIDIdevice(const MIDIPacketList *pktlist, void *refCon, void *co
     } // j-loop through the list of packets
 }
 
-void close_midi_device() {
-    fprintf(stderr,"%s\n",__FUNCTION__);
+//
+// store the ports and clients locally such that we
+// can properly close a MIDI connection
+//
+static MIDIPortRef myMIDIports[MAX_MIDI_DEVICES];
+static MIDIClientRef myClients[MAX_MIDI_DEVICES];
+
+void close_midi_device(index) {
+    fprintf(stderr,"%s index=\n",__FUNCTION__);
+    if (index < 0 || index > n_midi_devices) return;
+    //
+    // This should release the resources associated with the pending connection
+    //
+    MIDIPortDisconnectSource(myMIDIports[index], MIDIGetSource(index));
+    MIDIPortDispose(myMIDIports[index]);
+    MIDIClientDispose(myClients[index]);
+    myMIDIports[index]=0;
+    myClients[index]=0;
 }
 
-int register_midi_device(char *myname) {
-    int i;
-    CFStringRef pname;
-    char name[100];
-    int FoundMIDIref=-1;
-    int mylen;
+int register_midi_device(int index) {
     int ret;
 
-    configure=false;
-    if (myname == NULL) {
-      g_print("%s: myname is NULL\n", __FUNCTION__);
-      return -1;
-    }
-    mylen=strlen(myname);
+    g_print("%s: index=%d\n",__FUNCTION__,index);
 
-    g_print("%s: %s\n",__FUNCTION__,myname);
-//
-// Go through the list of MIDI devices and
-// look whether the one we are looking for is there
-//
-    for (i=0; i<n_midi_devices; i++) {
-        if(!strncmp(midi_devices[i].name, myname, mylen)) {
-           FoundMIDIref=i;
-           fprintf(stderr,"MIDI device found and selected: >>>%s<<<\n", midi_devices[i].name);
-       } else {
-           fprintf(stderr,"MIDI device found BUT NOT SELECTED: >>>%s<<<\n", midi_devices[i].name);
-       }
-    }
 
 //
-// If we found "our" device, register a callback routine
+//  Register a callback routine for the device
 //
 
-    if (FoundMIDIref >= 0) {
-        MIDIClientRef client = 0;
-        MIDIPortRef myMIDIport = 0;
-        //Create client
-        MIDIClientCreate(CFSTR("piHPSDR"),NULL,NULL, &client);
-        MIDIInputPortCreate(client, CFSTR("FromMIDI"), ReadMIDIdevice, NULL, &myMIDIport);
-        MIDIPortConnectSource(myMIDIport,MIDIGetSource(FoundMIDIref), NULL);
+    if (index >= 0 && index < n_midi_devices) {
+        myClients[index]=0;
+        myMIDIports[index] = 0;
+        //Create client and port, and connect
+        MIDIClientCreate(CFSTR("piHPSDR"),NULL,NULL, &myClients[index]);
+        MIDIInputPortCreate(myClients[index], CFSTR("FromMIDI"), ReadMIDIdevice, NULL, &myMIDIports[index]);
+        MIDIPortConnectSource(myMIDIports[index] ,MIDIGetSource(index), NULL);
         ret=0;
     } else {
         ret=-1;
@@ -262,6 +245,9 @@ void get_midi_devices() {
             //
             if (strlen(name) == 0) strcpy(name,"NoPort");
             g_print("%s: %s\n",__FUNCTION__,name);
+            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(name)+1);
             strcpy(midi_devices[n_midi_devices].name,name);
             n_midi_devices++;
diff --git a/midi.h b/midi.h
index 72cd62a659c00c948c53ba53f6fbe0c214a2001b..a617e0c3bc37f8f6e13b312ba753581c14db766f 100644 (file)
--- a/midi.h
+++ b/midi.h
@@ -269,8 +269,8 @@ extern int midi_debug;
 // that have been defined. This is called upon startup by
 // Layer-2 through the function MIDIstartup.
 //
-int register_midi_device(char *name);
-void close_midi_device();
+int register_midi_device(int index);
+void close_midi_device(int index);
 void configure_midi_device(gboolean state);
 
 //
diff --git a/midi2.c b/midi2.c
index e13b36e11d05b664fd788a90d77b4e0abb4ae6f3..202be3235c84eb49db5c8909ac7ae7ce42682113 100644 (file)
--- a/midi2.c
+++ b/midi2.c
@@ -25,9 +25,7 @@
 #include "radio.h"
 #include "main.h"
 #include "midi.h"
-
-static double midi_startup_time;
-static int    midi_wait_startup=0;
+#include "alsa_midi.h"
 
 struct desc *MidiCommandsTable[129];
 
@@ -46,20 +44,6 @@ void NewMidiEvent(enum MIDIevent event, int channel, int note, int val) {
 //now=ts.tv_sec + 1E-9*ts.tv_nsec;
 //g_print("%s:%12.3f:EVENT=%d CHAN=%d NOTE=%d VAL=%d\n",__FUNCTION__,now,event,channel,note,val);
 
-    //
-    // the midi_wait_startup/midi_startup_time mechanism takes care that in the first
-    // second after registering a MIDI device, all incoming MIDI messages are just discarded.
-    // This has been introduced since sometimes "old" MIDI messages are lingering around in the
-    // the system and get delivered immediately after registering the MIDI device.
-    // The midi_wait_startup variable takes care that we do not check the clock again and again
-    // after the first second.
-    //
-    if (midi_wait_startup) {
-      clock_gettime(CLOCK_MONOTONIC, &ts);
-      now=ts.tv_sec + 1E-9*ts.tv_nsec;
-      if (now < midi_startup_time + 1.0) return;
-      midi_wait_startup=0;
-    }
     if (event == MIDI_EVENT_PITCH) {
        desc=MidiCommandsTable[128];
     } else {
@@ -278,7 +262,11 @@ static void keyword2action(char *s, enum MIDIaction *action, int *onoff) {
 
 int MIDIstop() {
   midi_enabled=FALSE;
-  close_midi_device();
+  for (int i=0; i<n_midi_devices; i++) {
+    if (midi_devices[i].active) {
+      close_midi_device(i);
+    }
+  }
   return 0;
 }
 
@@ -347,7 +335,6 @@ int MIDIstartup(char *filename) {
     enum MIDIevent event;
     int i;
     char c;
-    struct timespec ts;
 
     MidiReleaseCommands();
 
@@ -385,20 +372,6 @@ int MIDIstartup(char *filename) {
       
 g_print("\n%s:INP:%s\n",__FUNCTION__,zeile);
 
-      if ((cp = strstr(zeile, "DEVICE="))) {
-        // Delete comments and trailing blanks
-       cq=cp+7;
-       while (*cq != 0 && *cq != '#') cq++;
-       *cq--=0;
-       while (cq > cp+7 && (*cq == ' ' || *cq == '\t')) cq--;
-       *(cq+1)=0;
-//fprintf(stderr,"MIDI:REG:>>>%s<<<\n",cp+7);
-        midi_wait_startup=1;
-        clock_gettime(CLOCK_MONOTONIC, &ts);
-        midi_startup_time=ts.tv_sec + 1E-9*ts.tv_nsec;
-       int result=register_midi_device(cp+7);
-        continue; // nothing more in this line
-      }
       chan=-1;  // default: any channel
       t1=t3=t5=t7= t9=t11=128;  // range that never occurs
       t2=t4=t6=t8=t10=t12=-1;   // range that never occurs
index 766e7dd23a43bd8a38d524796628455ba2ad6996..bea800ae824ca0de62284c286e85a3a4fc5d541a 100644 (file)
@@ -75,9 +75,11 @@ static GtkWidget *newMin;
 static GtkWidget *newMax;
 static GtkWidget *newAction;
 static GtkWidget *configure_b;
+static GtkWidget *any_b;
 static GtkWidget *add_b;
 static GtkWidget *update_b;
 static GtkWidget *delete_b;
+static GtkWidget *device_b[MAX_MIDI_DEVICES];
 
 static enum MIDIevent thisEvent=MIDI_EVENT_NONE;
 static int thisChannel;
@@ -88,8 +90,7 @@ static int thisMax;
 static enum MIDItype thisType;
 static enum MIDIaction thisAction;
 
-gchar *midi_device_name=NULL;
-static gint device_index=-1;
+static gboolean accept_any=FALSE;
 
 enum {
   UPDATE_NEW,
@@ -121,38 +122,50 @@ static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_d
 }
 
 static gboolean midi_enable_cb(GtkWidget *widget,gpointer data) {
+  int i;
   if(midi_enabled) {
-    close_midi_device();
+    for (i=0; i<n_midi_devices; i++) {
+      if (midi_devices[i].active) {
+        close_midi_device(i);
+      }
+    }
   }
   midi_enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
   if(midi_enabled) {
-    if(register_midi_device(midi_device_name)<0) {
-      midi_enabled=FALSE;
-      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (widget), midi_enabled);
+    for (i=0; i<n_midi_devices; i++) {
+      if (midi_devices[i].active) {
+        register_midi_device(i);
+      }
     }
   }
   return TRUE;
 }
 
+static void device_cb(GtkWidget *widget, gpointer data) {
+  int index=GPOINTER_TO_INT(data);
+  int val=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+  g_print("DEVICE =%d STATUS=%d\n", index, val);
+  midi_devices[index].active=val;
+  if (val == 1) {
+    register_midi_device(index);
+  } else {
+    close_midi_device(index);
+  }
+}
+
 static void configure_cb(GtkWidget *widget, gpointer data) {
   gboolean conf=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
   configure_midi_device(conf);
+  if (conf) {
+    gtk_widget_show(any_b);
+  } else {
+    gtk_widget_hide(any_b);
+  }
 }
 
-static void device_changed_cb(GtkWidget *widget, gpointer data) {
-  device_index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
-  if(midi_device_name!=NULL) {
-    g_free(midi_device_name);
-  }
-  midi_device_name=g_new(gchar,strlen(midi_devices[device_index].name)+1);
-  strcpy(midi_device_name,midi_devices[device_index].name);
-  if(midi_enabled) {
-    close_midi_device();
-    if(register_midi_device(midi_device_name)) {
-      midi_enabled=FALSE;
-      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(midi_enable_b), midi_enabled);
-    }
-  }
+static void any_cb(GtkWidget *widget, gpointer data) {
+  gboolean conf=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
+  accept_any = conf;
 }
 
 static void type_changed_cb(GtkWidget *widget, gpointer data) {
@@ -242,7 +255,11 @@ static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer dat
         } else {
           thisEvent=MIDI_EVENT_NONE;
         }
-        thisChannel=atoi(str_channel);
+        if (!strncmp(str_channel,"Any", 3)) {
+          thisChannel=-1;
+        } else {
+          thisChannel=atoi(str_channel);
+        }
         thisNote=atoi(str_note);
         thisVal=0;
         thisMin=0;
@@ -276,7 +293,7 @@ static void find_current_cmd() {
   g_print("%s:\n",__FUNCTION__);
   cmd=MidiCommandsTable[thisNote];
   while(cmd!=NULL) {
-    if((cmd->channel==thisChannel || cmd->channel==-1) && cmd->type==thisType && cmd->action==thisAction) {
+    if((cmd->channel==thisChannel) && cmd->type==thisType && cmd->action==thisAction) {
       g_print("%s: found cmd %p\n",__FUNCTION__,cmd);
       break;
     }
@@ -313,13 +330,8 @@ static void save_cb(GtkWidget *widget,gpointer user_data) {
                                       NULL);
   chooser = GTK_FILE_CHOOSER (save_dialog);
   gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE);
-  if(midi_device_name==NULL) {
-    filename=g_new(gchar,10);
-    sprintf(filename,"midi.midi");
-  } else {
-    filename=g_new(gchar,strlen(midi_device_name)+6);
-    sprintf(filename,"%s.midi",midi_device_name);
-  }
+  filename=g_new(gchar,10);
+  sprintf(filename,"midi.midi");
   gtk_file_chooser_set_current_name(chooser,filename);
   res = gtk_dialog_run (GTK_DIALOG (save_dialog));
   if(res==GTK_RESPONSE_ACCEPT) {
@@ -350,13 +362,8 @@ static void load_cb(GtkWidget *widget,gpointer user_data) {
                                       GTK_RESPONSE_ACCEPT,
                                       NULL);
   chooser = GTK_FILE_CHOOSER (load_dialog);
-  if(midi_device_name==NULL) {
-    filename=g_new(gchar,10);
-    sprintf(filename,"midi.midi");
-  } else {
-    filename=g_new(gchar,strlen(midi_device_name)+6);
-    sprintf(filename,"%s.midi",midi_device_name);
-  }
+  filename=g_new(gchar,10);
+  sprintf(filename,"midi.midi");
   gtk_file_chooser_set_current_name(chooser,filename);
   res = gtk_dialog_run (GTK_DIALOG (load_dialog));
   if(res==GTK_RESPONSE_ACCEPT) {
@@ -389,13 +396,8 @@ static void load_original_cb(GtkWidget *widget,gpointer user_data) {
                                       GTK_RESPONSE_ACCEPT,
                                       NULL);
   chooser = GTK_FILE_CHOOSER (load_dialog);
-  if(midi_device_name==NULL) {
-    filename=g_new(gchar,10);
-    sprintf(filename,"midi.midi");
-  } else {
-    filename=g_new(gchar,strlen(midi_device_name)+6);
-    sprintf(filename,"%s.midi",midi_device_name);
-  }
+  filename=g_new(gchar,10);
+  sprintf(filename,"midi.midi");
   gtk_file_chooser_set_current_name(chooser,filename);
   res = gtk_dialog_run (GTK_DIALOG (load_dialog));
   if(res==GTK_RESPONSE_ACCEPT) {
@@ -674,6 +676,10 @@ void midi_menu(GtkWidget *parent) {
   int row=0;
   GtkCellRenderer *renderer;
 
+  g_print("MENU: ndev=%d\n", n_midi_devices);
+  for (i=0; i<n_midi_devices; i++) {
+    g_print("Name=%s Active=%d\n", midi_devices[i].name, midi_devices[i].active);
+  }
   dialog=gtk_dialog_new();
   gtk_window_set_transient_for(GTK_WINDOW(dialog),GTK_WINDOW(parent_window));
   char title[64];
@@ -696,36 +702,56 @@ void midi_menu(GtkWidget *parent) {
   row=0;
   col=0;
 
-  get_midi_devices();
-  if(n_midi_devices>0) {
-    GtkWidget *devices_label=gtk_label_new("Select MIDI device: ");
-    gtk_grid_attach(GTK_GRID(grid),devices_label,col,row,3,1);
-    col+=3;
-
-    GtkWidget *devices=gtk_combo_box_text_new();
-    for(int i=0;i<n_midi_devices;i++) {
-      gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(devices),NULL,midi_devices[i].name);
-      if(midi_device_name!=NULL) {
-        if(strcmp(midi_device_name,midi_devices[i].name)==0) {
-          device_index=i;
-        }
+  //get_midi_devices();
+  if (n_midi_devices > 0) {
+    GtkWidget *devices_label=gtk_label_new(NULL);
+    gtk_label_set_markup(GTK_LABEL(devices_label), "<b>Select MIDI device(s)</b>");
+    gtk_label_set_justify(GTK_LABEL(devices_label),GTK_JUSTIFY_LEFT);
+    gtk_grid_attach(GTK_GRID(grid),devices_label,row,col,2,1);
+    col +=2;
+    for (i=0; i<n_midi_devices; i++) {
+      device_b[i] = gtk_check_button_new_with_label(midi_devices[i].name);
+      gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(device_b[i]), midi_devices[i].active);
+      gtk_grid_attach(GTK_GRID(grid),device_b[i],col,row,2,1);
+      col +=2;
+      if (col == 8) {
+        col=2;
+        row++;
       }
+      g_signal_connect(device_b[i], "toggled", G_CALLBACK(device_cb), GINT_TO_POINTER(i));
+      gtk_widget_show(device_b[i]);
+    }
+    if (col > 0) {
+      col=0;
+      row++;
     }
-    gtk_grid_attach(GTK_GRID(grid),devices,col,row,6,1);
-    gtk_combo_box_set_active(GTK_COMBO_BOX(devices),device_index);
-    g_signal_connect(devices,"changed",G_CALLBACK(device_changed_cb),NULL);
   } else {
-    GtkWidget *message=gtk_label_new("No MIDI devices found!");
-    gtk_grid_attach(GTK_GRID(grid),message,col,row,1,1);
+    GtkWidget *devices_label=gtk_label_new(NULL);
+    gtk_label_set_markup(GTK_LABEL(devices_label), "<b>No MIDI devices found!</b>");
+    gtk_label_set_justify(GTK_LABEL(devices_label),GTK_JUSTIFY_LEFT);
+    gtk_grid_attach(GTK_GRID(grid),devices_label,col,row,3,1);
+    row=1;
+    col=0;
   }
-  row++;
-  col=0;
+
 
   midi_enable_b=gtk_check_button_new_with_label("MIDI Enable");
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (midi_enable_b), midi_enabled);
-  gtk_grid_attach(GTK_GRID(grid),midi_enable_b,col,row,3,1);
+  gtk_grid_attach(GTK_GRID(grid),midi_enable_b,col,row,2,1);
   g_signal_connect(midi_enable_b,"toggled",G_CALLBACK(midi_enable_cb),NULL);
 
+  col+=2;
+  configure_b=gtk_check_button_new_with_label("MIDI Configure");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (configure_b), FALSE);
+  gtk_grid_attach(GTK_GRID(grid),configure_b,col,row,2,1);
+  g_signal_connect(configure_b,"toggled",G_CALLBACK(configure_cb),NULL);
+
+  col+=2;
+  any_b=gtk_check_button_new_with_label("Configure for any channel");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (any_b), FALSE);
+  gtk_grid_attach(GTK_GRID(grid),any_b,col,row,6,1);
+  g_signal_connect(any_b,"toggled",G_CALLBACK(any_cb),NULL);
+
   row++;
   col=0;
 
@@ -749,15 +775,6 @@ void midi_menu(GtkWidget *parent) {
   g_signal_connect(load_original_b,"clicked",G_CALLBACK(load_original_cb),NULL);
   col++;
 
-  row++;
-  col=0;
-
-  configure_b=gtk_check_button_new_with_label("MIDI Configure");
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (configure_b), FALSE);
-  gtk_grid_attach(GTK_GRID(grid),configure_b,col,row,3,1);
-  g_signal_connect(configure_b,"toggled",G_CALLBACK(configure_cb),NULL);
-
-
   row++;
   col=0;
   GtkWidget *label=gtk_label_new("Evt");
@@ -859,6 +876,7 @@ void midi_menu(GtkWidget *parent) {
   gtk_container_add(GTK_CONTAINER(content),grid);
   sub_menu=dialog;
   gtk_widget_show_all(dialog);
+  gtk_widget_hide(any_b);
 }
 
 static int update(void *data) {
@@ -884,7 +902,11 @@ static int update(void *data) {
           gtk_label_set_text(GTK_LABEL(newEvent),"PITCH");
           break;
       }
-      sprintf(text,"%d",thisChannel);
+      if (thisChannel >= 0) {
+        sprintf(text,"%d",thisChannel);
+      } else {
+        strcpy(text,"Any");
+      }
       gtk_label_set_text(GTK_LABEL(newChannel),text);
       sprintf(text,"%d",thisNote);
       gtk_label_set_text(GTK_LABEL(newNote),text);
@@ -1037,6 +1059,7 @@ void NewMidiConfigureEvent(enum MIDIevent event, int channel, int note, int val)
     //g_print("%s: new or existing event\n",__FUNCTION__);
     thisEvent=event;
     thisChannel=channel;
+    if (accept_any) thisChannel=-1;
     thisNote=note;
     thisVal=val;
     thisMin=val;
@@ -1065,10 +1088,14 @@ void NewMidiConfigureEvent(enum MIDIevent event, int channel, int note, int val)
         } else {
           tree_event=MIDI_EVENT_NONE;
         }
-        tree_channel=atoi(str_channel);
+        if (!strncmp(str_channel,"Any", 3)) {
+         tree_channel=-1;
+        } else {
+          tree_channel=atoi(str_channel);
+        }
         tree_note=atoi(str_note);
 
-       if(thisEvent==tree_event && (thisChannel==tree_channel || tree_channel==-1) && thisNote==tree_note) {
+       if(thisEvent==tree_event && thisChannel==tree_channel && thisNote==tree_note) {
           thisVal=0;
           thisMin=0;
           thisMax=0;
@@ -1109,8 +1136,15 @@ void midi_save_state() {
   struct desc *cmd;
   gint index;
 
-  if(device_index!=-1) {
-    setProperty("midi_device",midi_devices[device_index].name);
+  index=0;
+  for (int i=0; i<n_midi_devices; i++) {
+    if (midi_devices[i].active) {
+      sprintf(name,"mididevice[%d].name",index);
+      setProperty(name, midi_devices[i].name);
+      index++;
+    }
+  }
+
     // the value i=128 is for the PitchBend
     for(int i=0;i<129;i++) {
       index=0;
@@ -1123,15 +1157,19 @@ void midi_save_state() {
         // These must not share the same key in the property database so the "running index" must be part of the key
         //
 
-        sprintf(name,"midi[%d].channel[%d].index[%d].event",i,cmd->channel,index);
+        sprintf(name,"midi[%d].index[%d].event",i,index);
         setProperty(name,midi_events[cmd->event]);
 
-        sprintf(name,"midi[%d].channel[%d].index[%d].type",i,cmd->channel,index);
+        sprintf(name,"midi[%d].index[%d].type",i,index);
         setProperty(name,midi_types[cmd->type]);
 
-        sprintf(name,"midi[%d].channel[%d].index[%d].action",i,cmd->channel,index);
+        sprintf(name,"midi[%d].index[%d].action",i,index);
         setProperty(name,(char *) ActionTable[cmd->action].str);
 
+        sprintf(name,"midi[%d].index[%d].channel",i,index);
+        sprintf(value,"%d",cmd->channel);
+        setProperty(name, value);
+
         cmd=cmd->next;
        index++;
       }
@@ -1143,7 +1181,6 @@ void midi_save_state() {
       }
 
     }
-  }
 }
 
 void midi_restore_state() {
@@ -1162,18 +1199,18 @@ void midi_restore_state() {
   MidiReleaseCommands();
 
   //g_print("%s\n",__FUNCTION__);
-  value=getProperty("midi_device");
-  if(value) {
-    //g_print("%s: device=%s\n",__FUNCTION__,value);
-    midi_device_name=g_new(gchar,strlen(value)+1);
-    strcpy(midi_device_name,value);
 
     
-    for(int i=0;i<n_midi_devices;i++) {
-      if(strcmp(midi_devices[i].name,value)==0) {
-        device_index=i;
-        g_print("%s: found device at %d\n",__FUNCTION__,i);
-        break;
+  for(int i=0; i<MAX_MIDI_DEVICES; i++) {
+    midi_devices[i].active=0;
+    sprintf(name,"mididevice[%d].name",i);
+    value=getProperty(name);
+    if (value) {
+      for (int j=0; j<n_midi_devices; j++) {
+        if(strcmp(midi_devices[j].name,value)==0) {
+          midi_devices[j].active=1;
+          g_print("%s: mark device %s at %d as active\n",__FUNCTION__,value,j);
+        }
       }
     }
   }
@@ -1185,7 +1222,7 @@ void midi_restore_state() {
     if(value) {
       indices=atoi(value);
       for(int index=0; index<indices; index++) {
-        sprintf(name,"midi[%d].channel[%d].index[%d].event",i,channel,index);
+        sprintf(name,"midi[%d].index[%d].event",i,index);
         value=getProperty(name);
        event=MIDI_EVENT_NONE;
         if(value) {
@@ -1196,7 +1233,7 @@ void midi_restore_state() {
             }
           }
        }
-        sprintf(name,"midi[%d].channel[%d].index[%d],type",i,channel,index);
+        sprintf(name,"midi[%d].index[%d].type",i,index);
         value=getProperty(name);
        type=MIDI_TYPE_NONE;
         if(value) {
@@ -1207,7 +1244,7 @@ void midi_restore_state() {
             }
           }
        }
-        sprintf(name,"midi[%d].channel[%d].index[%d].action",i,channel,index);
+        sprintf(name,"midi[%d].index[%d].action",i,index);
         value=getProperty(name);
        action=MIDI_ACTION_NONE;
         if(value) {
@@ -1220,6 +1257,14 @@ void midi_restore_state() {
            j++;
          }
        }
+        sprintf(name,"midi[%d].index[%d].channel",i,index);
+        onoff=ActionTable[action].onoff;
+        value=getProperty(name);
+        channel=-1;
+        if (value) {
+          channel=atoi(value);
+          if (channel < -2 || channel > 15) channel=0;
+        }
 
        struct desc *desc;
         desc = (struct desc *) malloc(sizeof(struct desc));
@@ -1227,7 +1272,7 @@ void midi_restore_state() {
         desc->action = action; // MIDIaction
         desc->type = type; // MIDItype
         desc->event = event; // MIDevent
-        desc->onoff = ActionTable[action].onoff;
+        desc->onoff = onoff;
         desc->delay = 0;
         desc->vfl1  = -1;
         desc->vfl2  = -1;
@@ -1243,7 +1288,7 @@ void midi_restore_state() {
         desc->vfr2  = 128;
         desc->channel  = channel;
 
-        g_print("DESK INIT Note=%d Action=%d Type=%d Event=%d OnOff=%d Chan=%d\n", i, action, type, event, onoff, channel);
+        //g_print("DESC INIT Note=%d Action=%d Type=%d Event=%d OnOff=%d Chan=%d\n", i, action, type, event, onoff, channel);
 
         MidiAddCommand(i, desc);
       } // index
index bed7e0a2fd34d455e854d1ae9b076bf9c53ed7e8..02220e18ab5f70351b17d1a410cfc1590a71fdb3 100644 (file)
@@ -17,7 +17,6 @@
 *
 */
 
-extern gchar *midi_device_name;
 extern void midi_menu(GtkWidget *parent);
 extern void NewMidiConfigureEvent(enum MIDIevent event, int channel, int note, int val);
 extern void midi_save_state();
index cf9b4a01743f1eb4ff00194b4afc40032c9db801..e1ed1e1cc196ece074b233c19103040a429487f6 100644 (file)
@@ -64,6 +64,7 @@
 #include "server_menu.h"
 #endif
 #ifdef MIDI
+#include "midi.h"
 #include "midi_menu.h"
 #endif
 
diff --git a/radio.c b/radio.c
index e086865ec3b8510c4ad0756ff2caf28a2a65e42f..8d7a314c75f21a37eba5fd7e4914e8731077055e 100644 (file)
--- a/radio.c
+++ b/radio.c
@@ -73,6 +73,7 @@
 #endif
 #include "rigctl_menu.h"
 #ifdef MIDI
+#include "midi.h"
 #include "alsa_midi.h"
 #include "midi_menu.h"
 #endif
@@ -1304,13 +1305,14 @@ void start_radio() {
   // running. So this is the last thing we do when starting the radio.
   //
 #ifdef MIDI
-  g_print("%s: midi_enabled=%d midi_device_name=%s\n",__FUNCTION__,midi_enabled,midi_device_name);
-  if(midi_enabled && (midi_device_name!=NULL)) {
-    if(register_midi_device(midi_device_name)<0) {
-      midi_enabled=FALSE;
+  g_print("%s: midi_enabled=%d \n",__FUNCTION__,midi_enabled);
+  if(midi_enabled) {
+    for (i=0; i<n_midi_devices; i++) {
+      if (midi_devices[i].active) {
+        g_print("%s: MIDI device %s (index=%d) registered\n", __FUNCTION__, midi_devices[i].name, i);
+        register_midi_device(i);
+      }
     }
-  } else {
-    midi_enabled=FALSE;
   }
 #endif