Hello.

Dave Phillips wrote:
If adding MIDI input capability in DOSemu is trivial, hopefully these reasons will convince you that it would still be greatly appreciated by some of us.
Thanks for checking this out, Stas !
OK.
Here goes the patch for midi input. Now at
least I don't feel myself that guilty for not
contributing for the half of a year already:)

About the patch:
- Must be applied against the CVS version, as
1.1.99.1 lacks the IRQ support for MPU401
needed for vapimpu.
- Don't forget to restart configure after
applying.
- Create a ~/.dosemu/dosemu-midi_in pipe and
forward your midi data to it.
- Let me know how it goes as I cant really test
it (no midi keyboard, and I am not a musician
at all).
--- src/include/config.h.in     Thu Aug 28 00:58:37 2003
+++ src/include/config.h.in     Fri Jan  9 02:16:16 2004
@@ -42,6 +42,7 @@
 #define  DEFAULT_CONFIG_SCRIPT "builtin"      /* main configuration script */
 #define  DOSEMU_LOGLEVEL    "dosemu.loglevel" /* logging configuration file */
 #define  DOSEMU_MIDI        "dosemu-midi"     /* fifo for midi daemon */
+#define  DOSEMU_MIDI_IN     "dosemu-midi_in"  /* fifo for midi input */
 
 EXTERN char *config_script_name INIT(DEFAULT_CONFIG_SCRIPT);
 EXTERN char *config_script_path INIT(0);
@@ -63,6 +64,7 @@
 EXTERN char *dexe_load_path INIT(dosemuhdimage_default);
 EXTERN char *ipx_dos_ini_path INIT(ALTERNATE_ETC "/dos.ini");
 EXTERN char *dosemu_midi_path INIT("~/" LOCALDIR_BASE_NAME "/run/" DOSEMU_MIDI);
+EXTERN char *dosemu_midi_in_path INIT("~/" LOCALDIR_BASE_NAME "/run/" DOSEMU_MIDI_IN);
 
 #define    DOSEMU_USERS_FILE     dosemu_users_file_path
 #define    DOSEMU_LOGLEVEL_FILE  dosemu_loglevel_file_path
@@ -76,6 +78,7 @@
 #define    IPX_DOS_INI_PATH      ipx_dos_ini_path
 #define    DOSEMU_MAP_PATH       dosemu_map_file_name
 #define    DOSEMU_MIDI_PATH      dosemu_midi_path
+#define    DOSEMU_MIDI_IN_PATH   dosemu_midi_in_path
 
 #endif /* not __ASM__ */
 
--- src/include/sound.h Sun Oct 26 19:35:57 2003
+++ src/include/sound.h Fri Jan  9 02:01:09 2004
@@ -227,6 +227,7 @@
 
 #define QUEUE_SIZE  64
 #define Q_HOLDS(q) (q.end - q.start)
+#define Q_AVAIL(q) (QUEUE_SIZE - q.end)
 #define Q_CLEAR(q) (q.start = q.end = 0)
 #define Q_PUT(q, v) { if (q.end < QUEUE_SIZE) q.output[q.end++] = v; }
 #define Q_GET(q) ({ \
@@ -234,6 +235,12 @@
     if (!Q_HOLDS(q)) Q_CLEAR(q); \
     __ret; \
 })
+#define Q_ADD(q, buf, len) ({ \
+    int __len = len; \
+    int __to_copy = MIN(__len, Q_AVAIL(q)); \
+    memcpy(q.output + q.end, buf, __to_copy); \
+    q.end += __to_copy; \
+})
 
 typedef struct {
   uint8_t  output[QUEUE_SIZE];  /* Output Queue */
@@ -256,6 +263,8 @@
        queue_t data;
        /* Architecture specific procedures */
        void (*data_write)(uint8_t data); /* process 1 MIDI byte */
+       int (*data_read)(uint8_t data[], int max_size);
+       void (*register_io_callback)(void (*io_callback)(void));
 } mpu401_info;
 
 /*
--- src/dosext/sound/sound.c    Sun Oct 26 19:35:57 2003
+++ src/dosext/sound/sound.c    Fri Jan  9 03:51:25 2004
@@ -347,7 +347,6 @@
      /* DSP 8-bit IRQ Ack - SB */
      S_printf("SB: 8-bit IRQ Ack: %x\n", SB_dsp.data);
      sb_deactivate_irq(SB_IRQ_8BIT);
-     SB_info.irq.active &= ~SB_IRQ_8BIT; /* may mean it never triggers! */
      SB_dsp.ready = 0x7f;
      if(SB_dsp.empty_state & DREQ_AT_EOI)
      {
@@ -361,7 +360,6 @@
    case 0x0F: /* 0x0F: DSP 16-bit IRQ - SB16 */
      S_printf("SB: 16-bit IRQ Ack: %x\n", SB_dsp.data);
      sb_deactivate_irq(SB_IRQ_16BIT);
-     SB_info.irq.active &= ~SB_IRQ_16BIT; /* may mean it never triggers! */
      SB_dsp.ready = 0x7f;
      if(SB_dsp.empty_state & DREQ_AT_EOI)
      {
@@ -648,7 +646,8 @@
   case 0:
     /* Read data port */
     r=Q_GET(mpu401_info.data);
-    S_printf("MPU401: Read data port = 0x%02x\n",r);
+    S_printf("MPU401: Read data port = 0x%02x, %i bytes still in queue\n",
+      r,Q_HOLDS(mpu401_info.data));
     sb_deactivate_irq(SB_IRQ_MIDI);
     break;
   case 1:
@@ -661,6 +660,17 @@
   return r;
 }
 
+static void mpu401_io_callback(void)
+{
+  char buf[QUEUE_SIZE];
+  int n;
+  n = mpu401_info.data_read(buf, QUEUE_SIZE);
+  if (n <= 0)
+    return;
+  S_printf("MPU401: Processing IO callback, %i bytes\n", n);
+  Q_ADD(mpu401_info.data, buf, n);
+  sb_activate_irq(SB_IRQ_MIDI);
+}
 
 /*
  * Main IO Routines - Write
@@ -1824,6 +1834,7 @@
        case 1:
                /* Write command port */
                S_printf("MPU401: Write 0x%02x to command port\n",value);
+               Q_CLEAR(mpu401_info.data);
                Q_PUT(mpu401_info.data, 0xfe); /* A command is sent: MPU_ACK it next 
time */
                sb_activate_irq(SB_IRQ_MIDI);
                switch (value) {
@@ -2596,7 +2607,7 @@
     SB_info.version = SB_NONE;
   }
 
-  (void) FM_driver_init();
+  FM_driver_init();
 }
 
 static void mpu401_init(void)
@@ -2627,7 +2638,9 @@
 
   Q_CLEAR(mpu401_info.data);
 
-  (void) MPU_driver_init();
+  MPU_driver_init();
+
+  mpu401_info.register_io_callback(mpu401_io_callback);
 }
 
 
@@ -2912,6 +2925,7 @@
       S_printf("SB: Untriggering scheduled IRQ\n");
       SB_dsp.empty_state &= ~IRQ_AT_EMPTY;
     }
+    SB_info.irq.active &= ~type;
     if(!(SB_info.irq.pending & type)) {
       return;
     }
--- src/base/init/parser.y.in   Sun Dec 28 06:22:09 2003
+++ src/base/init/parser.y.in   Fri Jan  9 02:14:42 2004
@@ -2215,6 +2215,7 @@
   LOCALDIR = get_dosemu_local_home();
   RUNDIR = mkdir_under(LOCALDIR, "run", 0);
   DOSEMU_MIDI_PATH = assemble_path(RUNDIR, DOSEMU_MIDI, 0);
+  DOSEMU_MIDI_IN_PATH = assemble_path(RUNDIR, DOSEMU_MIDI_IN, 0);
 }
 
 static void lax_user_checking(void)
--- src/arch/linux/dosext/sound/linux_sound.c   Sat Oct 11 16:54:05 2003
+++ src/arch/linux/dosext/sound/linux_sound.c   Fri Jan  9 02:27:26 2004
@@ -65,6 +65,7 @@
 
 /* MPU static vars */
 static int mpu_fd = -1;                     /* -1 = closed */
+static int mpu_in_fd = -1;                  /* -1 = closed */
 static boolean mpu_disabled = FALSE; /* TRUE if MIDI output disabled */
 
 static void linux_sb_dma_set_blocksize(int blocksize, int fragsize)
@@ -653,9 +654,6 @@
   SB_driver.DMA_complete        = linux_sb_dma_complete;
   SB_driver.DMA_set_blocksize   = linux_sb_dma_set_blocksize;
    
-  /* MPU-401 Functions */
-  mpu401_info.data_write = linux_mpu401_data_write;
-
   /* Miscellaneous Functions */
   SB_driver.set_speed           = linux_sb_set_speed;
   SB_driver.play_buffer         = NULL;
@@ -701,6 +699,11 @@
   return linux_sb_get_version();
 }
 
+void linux_mpu401_register_callback(void (*io_callback)(void))
+{
+  if (mpu_in_fd == -1) return;
+  add_to_io_select(mpu_in_fd, 1, io_callback);
+}
 
 void linux_mpu401_data_write(uint8_t data)
 {
@@ -724,6 +727,17 @@
        }
 }
 
+int linux_mpu401_data_read(uint8_t data[], int max_len)
+{
+       int ret;
+       if (mpu_in_fd == -1) return 0;
+       if ((ret = read(mpu_in_fd,data,max_len)) == -1) {
+                       S_printf("MPU401:[Linux] Failed to write to file 'midi' 
(%s)\n",
+                       strerror(errno));
+       }
+       return ret;
+}
+
 
 int FM_driver_init(void)
 {
@@ -735,6 +749,14 @@
 int MPU_driver_init(void)
 {
   S_printf("MPU:[Linux] MPU Driver Initialisation Called\n");
+
+  /* MPU-401 Functions */
+  mpu401_info.data_write = linux_mpu401_data_write;
+  mpu401_info.data_read = linux_mpu401_data_read;
+  mpu401_info.register_io_callback = linux_mpu401_register_callback;
+
+  mpu_in_fd = RPT_SYSCALL(open(DOSEMU_MIDI_IN_PATH, O_RDONLY | O_NONBLOCK, 0777));
+
   mpu_disabled = FALSE;
   /* Output a MIDI byte to an external file */
   /* Added NONBLOCK to prevent hanging - Karcher */
--- src/arch/linux/dosext/sound/linux_sound.h   Mon Oct  6 22:16:11 2003
+++ src/arch/linux/dosext/sound/linux_sound.h   Fri Jan  9 01:24:20 2004
@@ -46,6 +46,8 @@
 
 void linux_sb_dma_complete(void);
 
+int linux_mpu401_data_read(uint8_t data[], int max_len);
 void linux_mpu401_data_write(uint8_t data);
+void linux_mpu401_register_callback(void (*io_callback)(void));
 
 int linux_sb_get_free_fragments(int *total, int *free, int *bytes);

Reply via email to