[Vm-dev] [commit][3483] update midi & scratch plugins to support MIDI plugin improvements

commits at squeakvm.org commits at squeakvm.org
Mon Nov 2 22:31:32 UTC 2015


Revision: 3483
Author:   rowledge
Date:     2015-11-02 14:31:32 -0800 (Mon, 02 Nov 2015)
Log Message:
-----------
update midi & scratch plugins to support MIDI plugin improvements

Modified Paths:
--------------
    branches/Cog/platforms/unix/plugins/MIDIPlugin/sqUnixMIDIALSA.inc
    branches/Cog/platforms/unix/plugins/ScratchPlugin/unixSeriaPort2Ops.c

Modified: branches/Cog/platforms/unix/plugins/MIDIPlugin/sqUnixMIDIALSA.inc
===================================================================
--- branches/Cog/platforms/unix/plugins/MIDIPlugin/sqUnixMIDIALSA.inc	2015-11-02 22:28:52 UTC (rev 3482)
+++ branches/Cog/platforms/unix/plugins/MIDIPlugin/sqUnixMIDIALSA.inc	2015-11-02 22:31:32 UTC (rev 3483)
@@ -30,7 +30,12 @@
  * Reformatted for and integrated into Squeak build by: ian at
  * squeakland dot oh are gee
  * 
- * Last edited: 2009-08-19 04:39:12 by piumarta on emilia-2.local
+ * Modified for Scratch on Raspberry Pi by Manabu Sugiura
+ * - Compatibility of MIDI instruments on Raspbian
+ * - YAMAHA NSX-1 and NSX-39
+ *   http://yamaha-webmusic.github.io/nsx1-apps/specs/ANMW820A-001-10-j.pdf
+ *
+ * Last edited: 2014-09-17 22:33:32 by manabu on raspberrypi
  */
 
 /*** MIDI Parameters (used with sqMIDIParameter function) ***/
@@ -143,6 +148,33 @@
   3, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
+/* Phonetic Symbols Buffer for YAMAHA NSX-1 */ 
+char ps[128];
+int ps_index = 0;
+
+/* Port information Buffers 
+
+Sample:
+-MIDI settings
+% acconet -o
+Port  Client name   Port name
+14:0  Midi Through  Midi Through Port-0
+20:0  NSX-39        NSX-39 MIDI 1
+128:0 TiMidity      TiMidity port 0
+128:1 TiMidity      TiMidity port 1
+128:2 TiMidity      TiMidity port 2
+128:3 TiMidity      TiMidity port 3
+
+-Port information Buffers
+portIds[14,20,128,128,128,128]
+portNums[0,0,0,1,2,3] 
+*/
+
+#define MAX_PORT_COUNT 256
+int portIds[MAX_PORT_COUNT]; // client ids
+int portNums[MAX_PORT_COUNT]; // port numbers
+int portTypes[MAX_PORT_COUNT] = {0}; // now ignore input client
+
 static void performMIDICmd(snd_seq_event_t *ev, int cmdByte, int arg1, int arg2);
 static void processMIDIByte(snd_seq_event_t *ev, int aByte);
 static void startMIDICommand(snd_seq_event_t *ev, int cmdByte);
@@ -155,23 +187,29 @@
 */
 int sqMIDIClosePort(int portNum)
 {
-  int ret= 0;
+  int ret = 0;
+  snd_seq_event_t ev;
 
-  if (portNum == 0)
-    {
-      if (out_port >= 0)
-	ret= snd_seq_delete_simple_port(seq, out_port);
+  if(portTypes[portNum] == 0){
+    if (out_port >= 0) {
+      char all_note_off[] = {MIDI_CMD_CONTROL, 0x7b, 0x00};
+      snd_seq_ev_set_sysex(&ev, sizeof(all_note_off), all_note_off);
+      snd_seq_ev_set_direct(&ev);
+      snd_seq_ev_set_source(&ev, 0);
+      snd_seq_ev_set_dest(&ev, portIds[portNum], 0);
+      snd_seq_event_output(seq, &ev);
+      snd_seq_drain_output(seq);
+      ret = snd_seq_delete_simple_port(seq, out_port);
       out_port= -1;
     }
-  else if (portNum == 1)
-    {
-      if (in_port >= 0)
+  } else if (portTypes[portNum] == 1) {
+    if (in_port >= 0) {
 	ret= snd_seq_delete_simple_port(seq, in_port);
       in_port= -1;
     }
-  else
+  } else {
     return interpreterProxy->success(false);
-
+  } 
   return ret;
 }
 
@@ -197,8 +235,40 @@
 int sqMIDIGetPortCount(void)
 {
   DPRINTF("sqMIDIGetPortCount\n");
+  snd_seq_client_info_t *cinfo;
+  snd_seq_port_info_t *pinfo;
+  
+  snd_seq_client_info_alloca(&cinfo);
+  snd_seq_client_info_set_client(cinfo, -1);
+  
+  int cap;
+  int count = 0;
+  int client;
+  
+  while (snd_seq_query_next_client(seq, cinfo) >= 0 ){
+    client = snd_seq_client_info_get_client(cinfo);
+
+    snd_seq_port_info_alloca(&pinfo);
+    snd_seq_port_info_set_client(pinfo, client);
+    snd_seq_port_info_set_port(pinfo, -1);
+    
+    // while the next port is available
+    while (snd_seq_query_next_port(seq, pinfo) >= 0) {
+      cap = snd_seq_port_info_get_capability(pinfo);
+      // select output ports
+      if ((cap & SND_SEQ_PORT_CAP_SUBS_WRITE) != 0 && snd_seq_client_id(seq) != snd_seq_port_info_get_client(pinfo)) {
+	if (snd_seq_client_id(seq) != snd_seq_port_info_get_client(pinfo)) { 
+	  if (count < MAX_PORT_COUNT && strcmp(snd_seq_client_info_get_name(cinfo), "Midi Through") != 0) { //skip Midi Through port
+	    portIds[count] = snd_seq_port_info_get_client(pinfo);
+	    portNums[count] = snd_seq_port_info_get_port(pinfo);
+	    count++;
+	  }
+	}
+      }
+    }
+  }
   success(true);
-  return 1;
+  return count; 
 }
 
 /* Return an integer indicating the directionality of the given
@@ -207,10 +277,11 @@
 */
 int sqMIDIGetPortDirectionality(int portNum)
 {
-  switch (portNum)
+  switch(portTypes[portNum])
     {
     case 0:	return 2;
-    case 1:	return 1;
+    case 1:	return 1; //TODO: modify
+    default:    return 0;
     }
   return interpreterProxy->success(false);
 }
@@ -221,17 +292,23 @@
 */
 int sqMIDIGetPortName(int portNum, int namePtr, int length)
 {
-  static char *userName[] = { "out", "in" };
+  int count;
+  snd_seq_client_info_t *cinfo;
+  char name[128];
+  char portNumStr[128];
 
-  if (portNum == 0 || portNum == 1)
-    {
-      int count= strlen(userName[portNum]);
+  snd_seq_client_info_alloca(&cinfo);
+  snd_seq_client_info_set_client(cinfo, -1);
+  snd_seq_get_any_client_info(seq, portIds[portNum], cinfo);
+  sprintf(portNumStr, "%d", portNums[portNum]);
+  sprintf(name, "%s <port:%s>", snd_seq_client_info_get_name(cinfo) , portNumStr);
+  count = strlen(name);
       if (count > length) count= length;
-      memcpy((void *)namePtr, userName, count);
+  memcpy((void *)namePtr, name, count);
+  
+  success(true);
       return count;
     }
-  return interpreterProxy->success(false);
-}
 
 /* Open the given port, if possible.  If non-zero, readSemaphoreIndex
    specifies the index in the external objects array of a semaphore to
@@ -245,9 +322,9 @@
 int sqMIDIOpenPort(int portNum, int readSemaIndex, int interfaceClockRate)
 {
   DPRINTF(("sqMIDIOpenPort(%d, %d, %d)\n", portNum, readSemaIndex, interfaceClockRate));
+  out_port = -1;
   int type= SND_SEQ_PORT_TYPE_APPLICATION;
-
-  switch (portNum)
+  switch (portTypes[portNum])
     {
     case 0:
       if (out_port < 0)
@@ -259,6 +336,12 @@
 	      success(false);
 	      return 0;
 	    }
+	  
+	  if (snd_seq_connect_to(seq, out_port, portIds[portNum], 0) < 0)
+            {
+              success(false);
+              return 0;
+            }
 	}
       break;
 
@@ -282,7 +365,7 @@
   snd_seq_queue_tempo_t *tempo= 0;
   snd_seq_queue_tempo_alloca(&tempo);
   snd_seq_queue_tempo_set_tempo(tempo, interfaceClockRate);
-  snd_seq_set_queue_tempo(seq, queue, tempo);
+  snd_seq_set_queue_tempo(seq, queue,  (snd_seq_queue_tempo_t*)tempo);
 
   success(true);
   return 0;
@@ -333,7 +416,7 @@
 	  {
 	    snd_seq_queue_tempo_t *tempo= 0;
 	    snd_seq_queue_tempo_alloca(&tempo);
-	    snd_seq_get_queue_tempo(seq, queue, &tempo);
+	    snd_seq_get_queue_tempo(seq, queue, tempo);
 	    return snd_seq_queue_tempo_get_tempo(tempo) / 1000.0;
 	  }
 	  break;
@@ -380,7 +463,7 @@
 	  snd_seq_queue_tempo_t *tempo= 0;
 	  snd_seq_queue_tempo_alloca(&tempo);
 	  snd_seq_queue_tempo_set_tempo(tempo, 1000.0 * newValue);
-	  snd_seq_set_queue_tempo(seq, queue, tempo);
+	  snd_seq_set_queue_tempo(seq, queue, (snd_seq_queue_tempo_t*)tempo);
 	}
 	break;
 
@@ -420,8 +503,7 @@
 */
 int sqMIDIPortWriteFromAt(int portNum, int count, int bufferPtr, int time)
 {
-  if (portNum == 0)
-    {
+  if (portTypes[portNum] == 0 || portTypes[portNum] == 1) {
       int i;
       snd_seq_event_t ev;
       unsigned char *bytePtr= (unsigned char *)bufferPtr;
@@ -449,8 +531,7 @@
 
 int midiInit(void)
 {
-  if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_INPUT|SND_SEQ_OPEN_OUTPUT, 0) < 0)
-    {
+  if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_INPUT|SND_SEQ_OPEN_OUTPUT, 0) < 0) {
       success(false);
       return 0;
     }
@@ -533,6 +614,7 @@
 
 static void processMIDIByte(snd_seq_event_t *ev, int aByte)
 {
+  int i;
   if (aByte > 247) return;	/* skip all real-time messages */
 
   switch (state)
@@ -577,6 +659,8 @@
       if (aByte < 128)
 	{
 	  /* skip a system exclusive data byte */
+       	  ps[ps_index] = aByte;
+          ps_index++;
 	}
       else
 	{
@@ -588,6 +672,13 @@
 		{
 		  processMIDIByte(ev, aByte);	/* if not endSysExclusive, byte is the start the next command */
 		}
+              else{
+		  ps[ps_index] = aByte;
+                  ps_index++;
+		  //ev->type = SND_SEQ_EVENT_SYSEX;
+                  snd_seq_ev_set_sysex(ev, ps_index +1 , ps);
+		  ps_index = 0;
+	      }
 	    }
 	}
       break;
@@ -619,7 +710,11 @@
     case 3:	/* start a variable length 'system exclusive' command */
       /* a system exclusive command clears running status */
       lastCmdByte= 0;
+      if(cmdByte == 240){
+        ps[ps_index] = cmdByte;
+	ps_index++;
+      }
       state= sysExclusive;
       break;
     }
-}
+}
\ No newline at end of file

Modified: branches/Cog/platforms/unix/plugins/ScratchPlugin/unixSeriaPort2Ops.c
===================================================================
--- branches/Cog/platforms/unix/plugins/ScratchPlugin/unixSeriaPort2Ops.c	2015-11-02 22:28:52 UTC (rev 3482)
+++ branches/Cog/platforms/unix/plugins/ScratchPlugin/unixSeriaPort2Ops.c	2015-11-02 22:31:32 UTC (rev 3483)
@@ -337,7 +337,7 @@
 }
 
 int isSerialPortDev(char *s) {
-	return isPrefix("ttyusb", s);
+	return isPrefix("ttyusb", s) || isPrefix("ttyAMA", s);
 }
 
 int isPrefix(char *prefix, char *s) {



More information about the Vm-dev mailing list