home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / DevCon / Orlando_1993 / Devcon93.4 / CAMD / examples / oldexamples / mm / mm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-12  |  21.0 KB  |  961 lines

  1. /* Midi Monitor - CAMD / Realtime V37 version */
  2.  
  3. #include <exec/types.h>
  4. #include <devices/timer.h>    /* for timeval */
  5.  
  6. #include <libraries/dos.h>
  7. #include <midi/camd.h>
  8. #include <midi/camdbase.h>
  9. #include <midi/realtimebase.h>    /* for TickFreq and TickErr */
  10. #include <midi/mididefs.h>
  11. #include <midi/midiprefs.h>    /* for MaxMidiUnits */
  12.  
  13. #include <ctype.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17.  
  18. #include <clib/camd_protos.h>
  19. #include <clib/exec_protos.h>
  20.  
  21. #include <pragmas/camd_pragmas.h>
  22.  
  23. #ifndef MAX
  24. #define MAX(a,b)        ((a) > (b) ? (a) : (b))
  25. #endif
  26. #ifndef MIN
  27. #define MIN(a,b)        ((a) < (b) ? (a) : (b))
  28. #endif
  29. #ifndef ABS
  30. #define ABS(x)          ((x) < 0 ? -(x) : (x))
  31. #endif
  32.  
  33. struct CamdBase *CamdBase;
  34. struct RealTimeBase *RealTimeBase;
  35. struct MidiNode *mi;
  36. struct MidiLink *inlink,*in2link,*outlink;
  37.  
  38. #define DISPF_Hex    0x0001
  39. #define DISPF_Interpret 0x0002
  40. #define DISPF_LongSysEx 0x0004
  41. #define DISPF_Time    0x0008
  42.  
  43. UWORD dispopts;
  44.  
  45. char *cmerr (long err);
  46. void process (void);
  47. void cleanup (void);
  48. void dumperr (register UBYTE err);
  49. void dumpmsg (MidiMsg *);
  50. void prttime (ULONG time);
  51. void prtchan (register MidiMsg *);
  52. void prtctrl (register MidiMsg *);
  53. void prtmode (register MidiMsg *);
  54. void prtsys (MidiMsg *);
  55. void prtrt (MidiMsg *);
  56. void prtex (MidiMsg *);
  57. void dumplong (long len);
  58. void xgeneric (ULONG len);
  59. void prtund (MidiMsg *);
  60.  
  61. void dump (register UBYTE *s, register int len);
  62. void dumpascii (register UBYTE *s, register int len);
  63. void gettv (ULONG time, register struct timeval *tv);
  64. void prtqtrframe (register UBYTE data);
  65.  
  66. void _wb_parse(void) {}
  67.  
  68.  
  69. /*
  70.  * Lattice control-c stop...
  71.  */
  72. int CXBRK(void) { return(0); }        /* Disable Lattice CTRL/C handling */
  73. int chkabort(void) { return(0); }    /* really */
  74.  
  75. struct MidiNode *CreateMidi(Tag tag, ...)
  76. {    return CreateMidiA((struct TagItem *)&tag );
  77. }
  78.  
  79. struct MidiLink *AddMidiLink(struct MidiNode *mi, LONG type, Tag tag, ...)
  80. {    return AddMidiLinkA(mi, type, (struct TagItem *)&tag );
  81. }
  82.  
  83.  
  84. /*******
  85. * Main * ------------------------------------------------------------------------
  86. *******/
  87. void main (int argc, char **argv)
  88. {
  89.     char *inlinkname = "in.0";
  90.     char *in2linkname = "in.0";
  91.     char *outlinkname = "out.0";
  92.  
  93.     if (argc > 1) inlinkname = argv[1];
  94.  
  95.     if (argc > 2) outlinkname = argv[2];
  96.  
  97.     printf("Linking with in.0\n");
  98.     printf("Also linking with incluster=%s\noutcluster=%s\n\n",inlinkname,outlinkname);
  99.  
  100.     if (RealTimeBase = (struct RealTimeBase *)OpenLibrary("realtime.library",37))
  101.     {
  102.         if (CamdBase = (struct CamdBase *)OpenLibrary("camd.library",37))
  103.         {
  104.             if (mi = CreateMidi (    MIDI_Name,        "MIDI Monitor",
  105.                                     MIDI_RecvSignal,SIGBREAKB_CTRL_E,
  106.                                     MIDI_MsgQueue,    255,
  107.                                     MIDI_ErrFilter,    CMEF_All,
  108.                                     MIDI_SysExSize,    8096,
  109.                                     TAG_END ))
  110.             {
  111.                 if (inlink = AddMidiLink(mi,MLTYPE_Receiver,
  112.                                         MLINK_Name,            "MIDI Monitor Link",
  113.                                         MLINK_Location,        inlinkname,
  114.                                         MLINK_EventMask,    CMF_All,
  115.                                         MLINK_Comment,        "MIDI Monitor [Input]",
  116.                                         MLINK_SysExFilter,    SXFM_Off,
  117.                                         MLINK_ChannelMask,    0xffffL,
  118.                                         TAG_END ))
  119.                 {
  120.     
  121.                     in2link = AddMidiLink(mi,MLTYPE_Receiver,
  122.                                         MLINK_Name,            "MIDI Monitor Link",
  123.                                         MLINK_Location,        in2linkname,
  124.                                             MLINK_EventMask,    CMF_All,
  125.                                         MLINK_Comment,        "MIDI Monitor [Input]",
  126.                                         MLINK_SysExFilter,    SXFM_Off,
  127.                                         MLINK_ChannelMask,    0xffffL,
  128.                                         TAG_END );
  129.     
  130.                     if (! (outlink = AddMidiLink(mi,MLTYPE_Sender,
  131.                                             MLINK_Name,            "MIDI Monitor Link",
  132.                                             MLINK_Location,        outlinkname,
  133.                                             MLINK_Comment,        "MIDI Monitor [Output]",
  134.                                             TAG_END )))
  135.                     {
  136.                         printf("Can't add output link\n");
  137.                     }
  138.     
  139.                     printf ("Ctrl-C to exit.\n");
  140.                     process();
  141.                 }
  142.             }
  143.         }
  144.     }
  145.     cleanup();
  146.     CloseLibrary ((struct Library *)CamdBase);
  147.     CloseLibrary ((struct Library *)RealTimeBase);
  148.     exit(0L);
  149. }
  150.  
  151.  
  152. void cleanup(void)
  153. {
  154.     if (mi)
  155.     {
  156.         RemoveMidiLink(outlink);
  157.         RemoveMidiLink(in2link);
  158.         RemoveMidiLink(inlink);
  159.         DeleteMidi (mi);
  160.         mi = NULL;
  161.     }
  162. }
  163.  
  164.  
  165. void process(void)
  166. {
  167.     ULONG sigmask = (SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_E);
  168.     MidiMsg msg;
  169.     UBYTE err;
  170.  
  171.     while (!(Wait(sigmask) & SIGBREAKF_CTRL_C))
  172.     {
  173.         if (err = GetMidiErr(mi)) dumperr (err);
  174.  
  175.         while (GetMidi (mi,&msg))
  176.         {
  177.             dumpmsg (&msg);
  178.         }
  179.     }
  180. }
  181.  
  182. void dumperr(register UBYTE err)
  183. {
  184.    if (dispopts & DISPF_Time) /* prttime(*MidiTime()); */
  185.  
  186.    printf ("***");
  187.    if (err & (UBYTE)CMEF_RecvOverflow) printf (" RecvOverflow");
  188.    if (err & (UBYTE)CMEF_RecvErr) printf (" RecvErr");
  189.    if (err & (UBYTE)CMEF_ParseMem) printf (" ParseMem");
  190.    if (err & (UBYTE)CMEF_SysExFull) printf (" SysExFull");
  191.    if (err & (UBYTE)CMEF_SysExTooBig) printf (" SysExTooBig");
  192.    if (err & (UBYTE)CMEF_BufferFull) printf (" BufferFull");
  193.    if (err & (UBYTE)CMEF_MsgErr) printf (" MsgErr");
  194.    printf ("\n");
  195. }
  196.  
  197. char *num (char *b, unsigned val)
  198. {
  199.    sprintf (b, dispopts & DISPF_Hex ? "%x" : "%u", val);
  200.    return b;
  201. }
  202.  
  203. char *snum (char *b, int val)
  204. {
  205.    sprintf (b, dispopts & DISPF_Hex ? "%x" : "%+d", val);
  206.    return b;
  207. }
  208.  
  209. char *notename (char *b, int note)
  210. {
  211.    static char *notes[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
  212.  
  213.    if (dispopts & DISPF_Interpret)
  214.       sprintf (b,"%s%d",notes[note%12],note/12-2);
  215.    else
  216.       sprintf (b,"%s",num(b,note));
  217.  
  218.    return b;
  219. }
  220.  
  221.  
  222. void dumpmsg (MidiMsg *msg)
  223. {
  224.    int type = MidiMsgType(msg);
  225.    if (dispopts & DISPF_Time){;} /* prttime(msg->mm_Time); */
  226.  
  227.    if (1L << type & CMF_Channel)
  228.       {
  229.       prtchan (msg);
  230.       }
  231.    else
  232.       switch (type)
  233.          {
  234.          case CMB_SysCom:
  235.          prtsys(msg);
  236.          break;
  237.  
  238.          case CMB_RealTime:
  239.          prtrt(msg);
  240.          break;
  241.  
  242.          case CMB_SysEx:
  243.          prtex(msg);
  244.          break;
  245.  
  246.          default:    /* probably won't get this */
  247.          prtund(msg);
  248.          break;
  249.          }
  250. }
  251.  
  252.  
  253. /* !!! time could be relative to the time the program started */
  254. /*
  255. void prtqtrframe (UBYTE data)
  256. {
  257.    struct timeval tv;
  258.  
  259.    gettv (time, &tv);
  260.    printf ("%d:%02d:%02d.%03d ", (int)(tv.tv_secs / 3600), (int)(tv.tv_secs / 60 % 60), (int)(tv.tv_secs % 60), (int)((tv.tv_micro + 500) / 1000));
  261. }
  262. */
  263. void gettv (ULONG time, register struct timeval *tv)
  264. {
  265.    unsigned long err = time/1000*ABS(RealTimeBase->TickErr) + (time%1000*ABS(RealTimeBase->TickErr)+500)/1000;
  266.  
  267.    tv->tv_secs = time / RealTimeBase->TickFreq;
  268.    tv->tv_micro = time % RealTimeBase->TickFreq * 1000000 / RealTimeBase->TickFreq;
  269.  
  270.    /* apply err */
  271.    if (RealTimeBase->TickErr >= 0)
  272.       {
  273.       tv->tv_secs += err / 1000000;
  274.       tv->tv_micro += err % 1000000;
  275.       }
  276.    else
  277.       {
  278.       tv->tv_secs -= err / 1000000 + 1;
  279.       tv->tv_micro -= err % 1000000 - 1000000;
  280.       }
  281.  
  282.    /* normalize timeval */
  283.    if (tv->tv_micro >= 1000000)
  284.       {
  285.       tv->tv_secs += tv->tv_micro / 1000000;
  286.       tv->tv_micro %= 1000000;
  287.       }
  288. }
  289.  
  290.  
  291.  
  292. /* print channel message */
  293.  
  294. void prtchan (MidiMsg *msg)
  295. {
  296.    unsigned chan = (msg->mm_Status & MS_ChanBits) + 1;
  297.    char b1[20],b2[20];
  298.    int type = MidiMsgType(msg);
  299.  
  300.    /* MIDI thru added by dart */
  301.    PutMidiMsg(outlink,msg);
  302.  
  303.    if (1L << type & CMF_Ctrl) prtctrl (msg);
  304.    else
  305.       switch (type)
  306.          {
  307.          case CMB_Note:
  308.          printf ("Nt%s:%d %s %s\n", noteon(msg) ? "Dn" : "Up", chan, notename(b1,msg->mm_Data1), num(b2,msg->mm_Data2));
  309.          break;
  310.  
  311.          case CMB_PolyPress:
  312.          printf ("Pp:%d %s %s\n", chan, notename(b1,msg->mm_Data1), num(b2,msg->mm_Data2));
  313.          break;
  314.  
  315.          case CMB_Prog:
  316.          printf ("Pg:%d %s\n", chan, num(b1,msg->mm_Data1+1));
  317.          break;
  318.  
  319.          case CMB_ChanPress:
  320.          printf ("Mp:%d %s\n", chan, num(b1,msg->mm_Data1));
  321.          break;
  322.  
  323.          case CMB_PitchBend:
  324.          printf ("Pw:%d %s\n", chan, snum(b1,MIDIWord(msg->mm_Data2,msg->mm_Data1)-PitchBendCenter));
  325.          break;
  326.  
  327.          case CMB_Mode:
  328.          prtmode (msg);
  329.          break;
  330.          }
  331. }
  332.  
  333.  
  334. void prtmode (register MidiMsg *msg)
  335. {
  336.    unsigned chan = (msg->mm_Status & MS_ChanBits) + 1;
  337.    register int md = msg->mm_Data1;
  338.    int val = msg->mm_Data2;
  339.    char b1[20],b2[20];
  340.  
  341.    printf ("Md:%d ",chan);
  342.    if (dispopts & DISPF_Interpret)
  343.       {
  344.       switch (md)
  345.          {
  346.          case MM_ResetCtrl:
  347.          printf ("Reset All Controllers\n");
  348.          break;
  349.  
  350.          case MM_Local:
  351.          printf ("Local Control %s\n",val ? "On" : "Off");
  352.          break;
  353.  
  354.          case MM_AllOff:
  355.          printf ("All Notes Off\n");
  356.          break;
  357.  
  358.          case MM_OmniOff:
  359.          printf ("Omni Off\n");
  360.          break;
  361.  
  362.          case MM_OmniOn:
  363.          printf ("Omni On\n");
  364.          break;
  365.  
  366.          case MM_Mono:
  367.          printf ("Mono %s\n",num(b1,val));
  368.          break;
  369.  
  370.          case MM_Poly:
  371.          printf ("Poly\n");
  372.          break;
  373.      }
  374.       }
  375.    else
  376.       printf ("#%s %s\n",num(b1,md),num(b2,val));
  377. }
  378.  
  379.  
  380. struct desc
  381. {
  382.    ULONG id;        /* need UWORD for matching ext id's */
  383.    char *desc;
  384. };
  385.  
  386.  
  387. char *finddesc (ULONG id, struct desc *list, int count)
  388. {
  389.    for (; count--; list++)
  390.       {
  391.       if (list->id == id) return list->desc;
  392.       }
  393.    return NULL;
  394. }
  395.  
  396.  
  397.  
  398. #define CMERRS (sizeof cmerrlist / sizeof cmerrlist[0])
  399.  
  400. static struct desc cmerrlist[] =
  401. {
  402.     { CME_NoMem,    "Out of memory" },
  403.     { CME_NoTimer,  "No free CIA channels" },
  404.     { CME_BadPrefs, "Bad midi.prefs file" },
  405. };
  406.  
  407. char *cmerr (long err)      /* CreateMidi() error codes */
  408. {
  409.    static char b[64];
  410.    char *errmsg;
  411.  
  412.    if (err >= CME_NoUnit(0) && err <= CME_NoUnit(3))
  413.       {
  414.       sprintf (b, "Unit %d open failure", (int)(err - CME_NoUnit(0)));
  415.       return b;
  416.       }
  417.  
  418.    if (errmsg = finddesc (err, cmerrlist, CMERRS)) return errmsg;
  419.  
  420.    sprintf (b, "IoErr=%ld", err);
  421.    return b;
  422. }
  423.  
  424.  
  425. #define CTRL1S (sizeof ctrl1list / sizeof ctrl1list[0])
  426. #define CTRL2S (sizeof ctrl2list / sizeof ctrl2list[0])
  427.  
  428. static struct desc ctrl2list[] =
  429. {
  430.     { MC_ModWheel,  "ModW" },
  431.     { MC_Breath,    "Breath" },
  432.     { MC_Foot,        "Foot" },
  433.     { MC_PortaTime, "Porta" },
  434.     { MC_DataEntry, "Data" },
  435.     { MC_Volume,    "Vol" },
  436.     { MC_Balance,   "Bal" },
  437.     { MC_Pan,        "Pan" },
  438.     { MC_Expression,"Exprs" },
  439.     { MC_General1,  "Gen1" },
  440.     { MC_General2,  "Gen2" },
  441.     { MC_General3,  "Gen3" },
  442.     { MC_General4,  "Gen4" },
  443. };
  444.  
  445. static struct desc ctrl1list[] =
  446. {
  447.     { MC_Sustain,   "Sustain" },
  448.     { MC_Porta,     "Porta" },
  449.     { MC_Sustenuto, "Sustenuto" },
  450.     { MC_SoftPedal, "Soft" },
  451.     { MC_Hold2,     "Hold2" },
  452.     { MC_General5,  "Gen5" },
  453.     { MC_General6,  "Gen6" },
  454.     { MC_General7,  "Gen7" },
  455.     { MC_General8,  "Gen8" },
  456.     { MC_ExtDepth,  "Ext Depth" },
  457.     { MC_TremoloDepth,    "Tremolo Depth" },
  458.     { MC_ChorusDepth,    "Chorus Depth" },
  459.     { MC_CelesteDepth,    "Celeste Depth" },
  460.     { MC_PhaserDepth,    "Phaser Depth" },
  461.  
  462.     { MC_DataIncr,  "Data +" },
  463.     { MC_DataDecr,  "Data -" },
  464.     { MC_NRPNL,     "Non-Reg Param(L)" },
  465.     { MC_NRPNH,     "Non-Reg Param(H)" },
  466.     { MC_RPNL,        "Reg Param(L)" },
  467.     { MC_RPNH,        "Reg Param(H)" }
  468. };
  469.  
  470. #define CTRLMIN CMB_CtrlMSB
  471.  
  472. char *ctrltypedesc[] = { "MSB", "LSB", "Switch", "Byte", "Param", "Undef" };
  473.  
  474.  
  475. void prtctrl (register MidiMsg *msg)
  476. {
  477.     unsigned chan = (msg->mm_Status & MS_ChanBits) + 1;
  478.     int type = MidiMsgType(msg);
  479.     register int ct = msg->mm_Data1;
  480.     int val = msg->mm_Data2;
  481.     char *desc;
  482.     char b1[20];
  483.  
  484.     printf ("Ct:%d ",chan);
  485.  
  486.     if (dispopts & DISPF_Interpret) {
  487.     switch (type) {
  488.         case CMB_CtrlMSB:
  489.         case CMB_CtrlLSB:
  490.             if (!(desc = finddesc ((ULONG)(ct & 31), ctrl2list, CTRL2S))) goto unknown;
  491.             printf ("%s(%c)", desc, ct>31 ? 'L' : 'H');
  492.             break;
  493.  
  494.         default:
  495.             if (!(desc = finddesc ((ULONG)ct, ctrl1list, CTRL1S))) goto unknown;
  496.             printf ("%s", desc);
  497.             break;
  498.  
  499.         unknown:
  500.             printf ("%s #%s", ctrltypedesc[type-CTRLMIN], num(b1,ct));
  501.             break;
  502.     }
  503.     }
  504.     else
  505.     printf ("#%s", num(b1,ct));
  506.  
  507.     printf (" %s\n", num(b1,val));
  508. }
  509.  
  510.  
  511. /* print system common */
  512.  
  513. void prtsys (MidiMsg *msg)
  514. {
  515.     char b1[20];
  516.  
  517.     switch (msg->mm_Status)
  518.       {
  519.     case MS_SongPos:
  520.         printf ("Pos %s\n", num(b1,MIDIWord(msg->mm_Data1,msg->mm_Data2)));
  521.         break;
  522.  
  523.     case MS_SongSelect:
  524.         printf ("Song %s\n", num(b1,msg->mm_Data1));
  525.         break;
  526.  
  527.     case MS_TuneReq:
  528.         printf ("Tune\n");
  529.         break;
  530.  
  531.     case MS_QtrFrame:
  532.         prtqtrframe (msg->mm_Data1);
  533.         break;
  534.  
  535.       #if 0    /* !!! shouldn't be able to get here */
  536.     default:
  537.         printf ("Und#%02x\n",msg->mm_Status);
  538.         break;
  539.       #endif
  540.     }
  541. }
  542.  
  543.  
  544. void prtqtrframe (register UBYTE data)
  545. {
  546.    static char *desc[] = { "FrameL", "FrameH", "SecL", "SecH", "MinL", "MinH", "HourL", "HourH" };
  547.    char b1[20];
  548.  
  549.    printf ("QtrFrame ");
  550.  
  551.    if (dispopts & DISPF_Interpret)
  552.       {
  553.       printf ("%s %s\n", desc[data>>4], num(b1,data & MTCQ_DataMask));
  554.       }
  555.    else printf ("%s\n",num(b1,data));
  556. }
  557.  
  558.  
  559. /* print real time */
  560.  
  561. void prtrt (MidiMsg *msg)
  562. {
  563.    static char *desc[] = { "Clk", "", "Start", "Cont", "Stop", "", "Actv", "Reset" };
  564.  
  565.    printf ("%s\n", desc[msg->mm_Status-MS_RealTime]);
  566. }
  567.  
  568.  
  569. /* print system exclusive */
  570.  
  571. #define IDS  (sizeof idlist / sizeof idlist[0])
  572.  
  573. static struct desc idlist[] =
  574. {
  575.     { MID_Sequential,    "Sequential" },
  576.     { MID_IDP,        "IDP" },
  577.     { MID_OctavePlateau,"Octave-Plataeu" },
  578.     { MID_Moog,     "Moog" },
  579.     { MID_Passport,    "Passport" },
  580.     { MID_Lexicon,    "Lexicon" },
  581.     { MID_Kurzweil,    "Kurzweil" },
  582.     { MID_Fender,    "Fender" },
  583.     { MID_Gulbransen,    "Gulbransen" },
  584.     { MID_AKG,        "AKG" },
  585.     { MID_Voyce,    "Voyce" },
  586.     { MID_Waveframe,    "Waveframe" },
  587.     { MID_ADA,        "ADA" },
  588.     { MID_Garfield,    "Garfield" },
  589.     { MID_Ensoniq,    "Ensoniq" },
  590.     { MID_Oberheim,    "Oberheim" },
  591.     { MID_Apple,    "Apple" },
  592.     { MID_GreyMatter,    "Grey Matter Response" },
  593.     { MID_PalmTree,    "Palm Tree" },
  594.     { MID_JLCooper,    "JL Cooper" },
  595.     { MID_Lowrey,    "Lowrey" },
  596.     { MID_AdamsSmith,    "Adams-Smith" },
  597.     { MID_Emu,        "E-Mu" },
  598.     { MID_Harmony,    "Harmony" },
  599.     { MID_ART,        "ART" },
  600.     { MID_Baldwin,    "Baldwin" },
  601.     { MID_Eventide,    "Eventide" },
  602.     { MID_Inventronics, "Inventronics" },
  603.     { MID_Clarity,    "Clarity" },
  604.  
  605.     { MID_SIEL,     "SIEL" },
  606.     { MID_Synthaxe,    "Synthaxe" },
  607.     { MID_Hohner,    "Hohner" },
  608.     { MID_Twister,    "Twister" },
  609.     { MID_Solton,    "Solton" },
  610.     { MID_Jellinghaus,    "Jellinghaus" },
  611.     { MID_Southworth,    "Southworth" },
  612.     { MID_PPG,        "PPG" },
  613.     { MID_JEN,        "JEN" },
  614.     { MID_SSL,        "SSL" },
  615.     { MID_AudioVeritrieb, "Audio Veritrieb" },
  616.     { MID_Elka,     "Elka" },
  617.     { MID_Dynacord,    "Dynacord" },
  618.     { MID_Clavia,    "Clavia" },
  619.     { MID_Soundcraft,    "Soundcraft" },
  620.  
  621.     { MID_Kawai,    "Kawai" },
  622.     { MID_Roland,    "Roland" },
  623.     { MID_Korg,     "Korg" },
  624.     { MID_Yamaha,    "Yamaha" },
  625.     { MID_Casio,    "Casio" },
  626.     { MID_Kamiya,    "Kamiya" },
  627.     { MID_Akai,     "Akai" },
  628.     { MID_JapanVictor,    "Japan Victor" },
  629.     { MID_Mesosha,    "Mesosha" },
  630.  
  631.     { MID_UNC,        "Non-Commercial" },
  632.     { MID_UNRT,     "Non-Real Time" },
  633.     { MID_URT,        "Real Time" }
  634. };
  635.  
  636.  
  637. #define XIDS (sizeof xidlist / sizeof xidlist[0])
  638.  
  639. static struct desc xidlist[] =
  640. {
  641.     { MIDX_DigitalMusic, "Digital Music" },
  642.     { MIDX_Iota,    "Iota" },
  643.     { MIDX_Artisyn,    "Artisyn" },
  644.     { MIDX_IVL,     "IVL" },
  645.     { MIDX_SouthernMusic, "Southern Music" },
  646.     { MIDX_LakeButler,    "Lake Butler" },
  647.     { MIDX_DOD,     "DOD" },
  648.     { MIDX_PerfectFret, "Perfect Fretworks" },
  649.     { MIDX_KAT,     "KAT" },
  650.     { MIDX_Opcode,    "Opcode" },
  651.     { MIDX_Rane,    "Rane" },
  652.     { MIDX_SpatialSound, "Spatial Sound" },
  653.     { MIDX_KMX,     "KMX" },
  654.     { MIDX_Brenell,    "Brenell" },
  655.     { MIDX_Peavey,    "Peavey" },
  656.     { MIDX_360,     "360" },
  657.     { MIDX_Axxes,    "Axxes" },
  658.     { MIDX_CAE,     "CAE" },
  659.     { MIDX_Cannon,    "Cannon" },
  660.     { MIDX_BlueSkyLogic,"Blue Sky Logic" },
  661.     { MIDX_Voce,    "Voce" },
  662. };
  663.  
  664. void prtex (MidiMsg *msg)
  665. {
  666.    UBYTE b[2];
  667.    UBYTE id;
  668.    ULONG xid;
  669.    ULONG len = QuerySysEx(mi);
  670.    char *idname=NULL;
  671.  
  672.    printf ("SysEx ");
  673.  
  674.    GetSysEx (mi, b, 1L);      /* throw away F0 */
  675.  
  676.    if (dispopts & DISPF_Interpret)
  677.       {
  678.       GetSysEx (mi, &id, 1L);
  679.  
  680.       printf ("id=");
  681.  
  682.       if (id == MID_XAmerica && QuerySysEx(mi) > 2)
  683.          {
  684.          GetSysEx (mi, b, 2L);
  685.          xid = MakeMIDX (id, b[0], b[1]);
  686.  
  687.          if (idname = finddesc(xid,xidlist,XIDS))
  688.             printf ("%s ", idname);
  689.          else
  690.             printf ("%02x-%04x ", (UBYTE)(xid>16), (UWORD)xid);
  691.          }
  692.       else
  693.          {
  694.          if (idname = finddesc((ULONG)id,idlist,IDS))
  695.             printf ("%s ",idname);
  696.      else
  697.         printf ("%02x ", id);
  698.      }
  699.       }
  700.  
  701.    xgeneric(len);
  702.  
  703.  
  704.   #if 0
  705.    if (dispopts & DISPF_Interpret)
  706.       {
  707.  
  708.       GetSysEx (mi, &id, 1L);
  709.  
  710.       if (id == MID_XAmerica && QuerySysEx(mi) > 2)
  711.          {
  712.          GetSysEx (mi, b, 2L);
  713.          xid = MakeMIDX (id, b[0], b[1]);
  714.  
  715.          if (idname = finddesc(xid,xidlist,XIDS))
  716.             {
  717.             printf ("%s ", idname);
  718.             switch (xid)
  719.                {
  720.                /* no manuf. specific processing yet */
  721.                default:
  722.                xgeneric();
  723.                break;
  724.                }
  725.             }
  726.          else
  727.             {
  728.             printf ("id=%02x-%04x ", (UBYTE)(xid>16), (UWORD)xid);
  729.             xgeneric();
  730.             }
  731.          }
  732.       else
  733.          {
  734.          if (idname = finddesc((ULONG)id,idlist,IDS))
  735.             {
  736.             printf ("%s ",idname);
  737.             switch (id)
  738.                {
  739.                case MID_Yamaha:
  740.                xyamaha();
  741.                break;
  742.  
  743.                case MID_Kawai:
  744.                xkawai();
  745.                break;
  746.  
  747.                default:
  748.                xgeneric();
  749.                break;
  750.                }
  751.             }
  752.          else
  753.             {
  754.             printf ("id=%02x ",id);
  755.             xgeneric();
  756.             }
  757.          }
  758.       }
  759.    else
  760.       {
  761.       xgeneric();
  762.       }
  763.   #endif
  764. }
  765.  
  766.  
  767. #define SHORTSX 8
  768.  
  769. void xgeneric (ULONG len)
  770. {
  771.    ULONG datalen = QuerySysEx(mi) - 1;     /* remove F7 */
  772.    UBYTE buf[SHORTSX];
  773.  
  774.    if (datalen > SHORTSX)
  775.       {
  776.       if (dispopts & DISPF_LongSysEx)
  777.          {
  778.          printf ("- %ld bytes\n", len);
  779.          dumplong (datalen);
  780.          printf ("\n");
  781.          }
  782.       else
  783.          {
  784.          GetSysEx (mi, buf, (long)SHORTSX);  /* should always get SHORTSX bytes unless QuerySysEx() is broken */
  785.          dump (buf,SHORTSX);
  786.          printf ("... (%ld total bytes)\n", len);
  787.          }
  788.       }
  789.    else
  790.       {
  791.       GetSysEx (mi, buf, datalen);            /* should always get datalen bytes unless QuerySysEx() is broken */
  792.       dump (buf,(int)datalen);
  793.       printf ("\n");
  794.       }
  795. }
  796.  
  797.  
  798. #if 0
  799.  
  800. void xyamaha(void)
  801. {
  802.    register unsigned chan;
  803.    UBYTE stat;
  804.    unsigned wd;
  805.    UBYTE b[16];
  806.    char b1[20],b2[20],b3[20],b4[20];
  807.  
  808.    if (GetSysEx (mi, &stat, 1L))
  809.       {
  810.       chan=(stat & 0xf) + 1;
  811.  
  812.       switch (stat & 0x70)
  813.          {
  814.      case YAMAHA_PARAMCHANGE:
  815.          GetSysEx (mi, b, 3L);
  816.          wd = MIDIWord(b[0],b[1]);
  817.          printf ("Param:%d %s:%s:%s %s\n", chan, num(b1,YAMAHA_PGROUP(wd)), num(b2,YAMAHA_PSUBGROUP(wd)), num(b3,YAMAHA_PNUM(wd)), num(b4,b[2]));
  818.          break;
  819.  
  820.          case YAMAHA_DUMPREQ:
  821.          GetSysEx (mi, b, 1L);
  822.          printf ("Request:%d fmt=%s\n", chan, num(b1,b[0]));
  823.          break;
  824.  
  825.          case YAMAHA_BULKDUMP:
  826.          xyamahadump (chan);
  827.          break;
  828.  
  829.      default:
  830.          printf ("Und#%02x ",stat);
  831.          xgeneric();
  832.          break;
  833.          }
  834.       }
  835.    else
  836.       {
  837.        printf ("\n");
  838.        return;
  839.        }
  840. }
  841.  
  842.  
  843. void xyamahadump (unsigned chan)
  844. {
  845.    int packetsize;
  846.    int first=1;
  847.    UBYTE b[2];
  848.    char b1[20];
  849.    char s[64];
  850.    long len;
  851.  
  852.    sprintf (s, "Dump:%d fmt=%s", chan, num(b1,*data++));
  853.  
  854.    while (GetSysEx (mi, b, 2L) == 2)
  855.       {
  856.       packetsize = MIDIWord(b[0],b[1]);
  857.  
  858.       if (first) printf ("%s", s);
  859.       else printf ("%*s", (int)strlen(s)+13, "...");
  860.  
  861.       /* printf (" size=%s sum=%02x", num(b1,packetsize), data[packetsize]); */
  862.       printf (" size=%s", num(b1,packetsize));
  863.  
  864.       len = QuerySysEx(mi)-3;
  865.       if (packetsize > len)
  866.          {     /* !!! can only detect a loss in the last packet */
  867.          printf (" (err: lost %s byte(s))", num(b1,(int)(packetsize-(len))));
  868.          }
  869.       printf ("\n");
  870.  
  871.       if (dispopts & DISPF_LongSysEx)
  872.          {
  873.          dumplong ((long)packetsize);
  874.          printf ("\n");
  875.      }
  876.       GetSysEx (mi,b,1L);     /* !!! sum */
  877.  
  878.       first = 0;
  879.       }
  880. }
  881.  
  882.  
  883. void xkawai(void)
  884. {
  885.    xgeneric();
  886. }
  887.  
  888. #endif
  889.  
  890.  
  891. #define ROWLEN 16
  892.  
  893. int chkskip(void);
  894.  
  895. void dumplong (long len)
  896. {
  897.    int ilen;
  898.    UBYTE buf[ROWLEN];
  899.  
  900.    chkskip();          /* clear CTRL_D signal */
  901.    printf ("    ");
  902.  
  903.    while (ilen = GetSysEx (mi, buf, (long)MIN(len,ROWLEN)))
  904.       {
  905.       if (chkskip())
  906.          {
  907.          printf ("^D\n");
  908.          break;
  909.          }
  910.       dump (buf,ilen);
  911.       printf ("%*s", (ROWLEN-ilen) * 3 + 1, "");
  912.       dumpascii (buf,ilen);
  913.       printf ("\n    ");
  914.       len -= ilen;
  915.       }
  916. }
  917.  
  918. #if 0
  919. void getrow(UBYTE *buf)
  920. {
  921.    int len;
  922.  
  923.    if (len = GetSysEx(mi,buf,(long)ROWLEN))
  924.       {
  925.       if (buf[len-1] == MS_EOX) len--;
  926.       }
  927.    return len;
  928. }
  929. #endif
  930.  
  931. void dump (register UBYTE *s, register int len)
  932. {
  933.    while (len--) printf ("%02x ",*s++);
  934. }
  935.  
  936. void dumpascii (register UBYTE *s, register int len)
  937. {
  938.    register int c;
  939.  
  940.    while (len--)
  941.       {
  942.       c = *s++;
  943.       putchar ( isprint(c) ? c : '.' );
  944.       }
  945. }
  946.  
  947.  
  948. int chkskip(void)
  949. {
  950.    return (SetSignal (0L,SIGBREAKF_CTRL_D) & SIGBREAKF_CTRL_D) != 0;
  951. }
  952.  
  953.  
  954. /* print undefined message (maybe raw?) */
  955.  
  956. void prtund (MidiMsg *msg)
  957. {
  958.    printf ("Und#%02x %02x %02x", msg->mm_Status, msg->mm_Data1, msg->mm_Data2);
  959. }
  960. /* eof */
  961.