home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 1 / GoldFishApril1994_CD1.img / d1xx / d101 / midi / dev / example / r.c < prev    next >
C/C++ Source or Header  |  1987-09-05  |  8KB  |  337 lines

  1. /* simple MIDI router */
  2. /*
  3.     This is considered an example even though it's included with the utility
  4.     set.  It shows methods for scanning public node lists and managing routes
  5.     to public nodes.  This might be used as the skeleton for a graphics-based
  6.     route manager.
  7. */
  8.  
  9. #include <exec/types.h>
  10. #include <exec/lists.h>
  11. #include <midi/midibase.h>
  12. #include <functions.h>
  13.  
  14. #define DeclareMinList(list)\
  15.     struct MinList list = { (void *)&list.mlh_Tail, NULL, (void *)&list.mlh_Head }
  16.  
  17.  
  18. struct MidiBase *MidiBase;
  19.  
  20. DeclareMinList(routelist);        /* list or MRoutePtr's for maintaining routes that we create */
  21.  
  22. main()
  23. {
  24.     char b[128];
  25.     extern int Enable_Abort;
  26.  
  27.     Enable_Abort = 0;            /* disable CTRL-C */
  28.  
  29.     if (!(MidiBase = (void *)OpenLibrary (MIDINAME,MIDIVERSION))) {
  30.     printf ("can't open midi.library\n");
  31.     goto clean;
  32.     }
  33.  
  34.     printf ("MIDI Router (type ? for help)\n");
  35.                     /* process commands */
  36.     for (;;) {
  37.     printf ("route> ");
  38.     if (gets(b) && !parse(b)) break;
  39.     }
  40.  
  41. clean:
  42.     if (MidiBase) CloseLibrary (MidiBase);
  43. }
  44.  
  45. parse(s)
  46. char *s;
  47. {
  48.     switch (tolower(*s++)) {
  49.     case 'x':           /* quit */
  50.     case 'q':
  51.         zaproutelist();
  52.         return 0;
  53.  
  54.     case 'l':           /* list */
  55.         list();
  56.         break;
  57.  
  58.     case 'a':           /* add */
  59.         addroute(s);
  60.         break;
  61.  
  62.     case 'm':           /* modify */
  63.         modroute(s);
  64.         break;
  65.  
  66.     case 'r':           /* remove */
  67.         remroute(s);
  68.         break;
  69.  
  70.     case 'h':           /* help */
  71.     case '?':
  72.         help();
  73.         break;
  74.     }
  75.     return 1;
  76. }
  77.  
  78.  
  79. help()
  80. {
  81.     printf ("\n");
  82.     printf ("Simple MIDI Router\n");
  83.     printf ("   ? - help\n");
  84.     printf ("   a <src> <dst> <MsgFlags> <ChanFlags> <ChanOffset> <NoteOffset> - add a route\n");
  85.     printf ("   m <num> <MsgFlags> <ChanFlags> <ChanOffset> <NoteOffset> - modify a route\n");
  86.     printf ("   r <num> - rem a route\n");
  87.     printf ("   l - list\n");
  88.     printf ("   q - quit\n");
  89.     printf ("\n");
  90. }
  91.  
  92.  
  93. list()
  94. {
  95.                 /* list public sources */
  96.     printf ("\nSources:\n");
  97.     listnames (&MidiBase->SourceList);
  98.                 /* list public dests */
  99.     printf ("\nDests:\n");
  100.     listnames (&MidiBase->DestList);
  101.                 /* list our routes */
  102.     printf ("\nRoutes:\n");
  103.     listroutes();
  104.     printf ("\n");
  105. }
  106.  
  107.  
  108. /*
  109.     Lists names in a specified list (like MidiBase->SourceList or MidiBase->DestList).
  110.     This requires locking the lists to prevent changes while scanning them.
  111.     Ideally, if a similar routine is going to take any large amount of time
  112.     or can be halted by the user in mid-stream, it should take a snapshot
  113.     of all the data it wishes to handle rather than locking the lists for
  114.     the whole process.    Locking the lists prevents anyone else from Creating
  115.     or Deleting a node or Finding a node.
  116. */
  117.  
  118. listnames(list)
  119. struct List *list;
  120. {
  121.     struct Node *node;
  122.  
  123.     LockMidiBase();
  124.     for (node = list->lh_Head; node->ln_Succ; node=node->ln_Succ) {
  125.     printf (" %s\n",node->ln_Name);
  126.     }
  127.     UnlockMidiBase();
  128. }
  129.  
  130.  
  131. /* Displays our route list. */
  132.  
  133. listroutes()
  134. {
  135.     struct MinNode *node;
  136.     int i;
  137.  
  138.     for (i=0,node = routelist.mlh_Head; node->mln_Succ; i++,node=node->mln_Succ) {
  139.     prtroute (i,node);
  140.     }
  141. }
  142.  
  143.  
  144. /*
  145.     Displays info about one of our routes.  In order to display the node
  146.     names, we need to lock the lists to ensure validity of the nodes.  This
  147.     one is done correctly:  it locks the lists, copies the names of the nodes
  148.     if present, unlocks the lists, and THEN prints.
  149. */
  150.  
  151. prtroute (i,rp)
  152. struct MRoutePtr *rp;
  153. {
  154.     struct MRoute *route = rp->Route;
  155.     struct MRouteInfo *ri = &route->RouteInfo;
  156.     struct MSource *source;
  157.     struct MDest *dest;
  158.     char sname[64], dname[64];
  159.  
  160.     LockMidiBase();            /* lock node lists */
  161.  
  162.     if (source = route->Source) {    /* if the source still exists */
  163.     if (source->Node.ln_Name)        /* and it has a name (public, for this program this should always be true) */
  164.         sprintf (sname,"\"%s\"",source->Node.ln_Name);      /* copy the name */
  165.     else
  166.         strcpy (sname,"(private)");
  167.     }
  168.     else {
  169.     strcpy (sname,"(removed)");
  170.     }
  171.  
  172.     if (dest = route->Dest) {        /* do the same for the dest */
  173.     if (dest->Node.ln_Name)
  174.         sprintf (dname,"\"%s\"",dest->Node.ln_Name);
  175.     else
  176.         strcpy (dname,"(private)");
  177.     }
  178.     else {
  179.     strcpy (dname,"(removed)");
  180.     }
  181.  
  182.     UnlockMidiBase();            /* unlock the lists */
  183.  
  184.                     /* print */
  185.     printf (" %2d: %08lxH %s->%s %04x %04x %d %d\n", i, route, sname, dname, ri->MsgFlags, ri->ChanFlags, ri->ChanOffset, ri->NoteOffset);
  186. }
  187.  
  188.  
  189. /* delete all routes in our route list, used on exit */
  190.  
  191. zaproutelist()
  192. {
  193.     struct MRoutePtr *rp;
  194.  
  195.     while (rp = (struct MRoutePtr *)RemHead(&routelist)) {
  196.     DeleteMRoute(rp->Route);
  197.     free (rp);
  198.     }
  199. }
  200.  
  201.  
  202. /* adds a new route based on the command line in s */
  203.  
  204. addroute(s)
  205. char *s;
  206. {
  207.     char sname[64],dname[64];
  208.     struct MRouteInfo ri;
  209.     struct MRoutePtr *rp=NULL;
  210.     struct MRoute *route=NULL;
  211.     int chanoffset,noteoffset;
  212.     void *calloc();
  213.  
  214.     setmem (&ri,sizeof ri,0);
  215.     if (sscanf (s,"%s%s%x%x%d%d",sname,dname,&ri.MsgFlags,&ri.ChanFlags,&chanoffset,¬eoffset) != 6) {
  216.     printf ("syntax error\n");
  217.     goto clean;
  218.     }
  219.     ri.ChanOffset = chanoffset;
  220.     ri.NoteOffset = noteoffset;
  221.  
  222.                 /* allocate a RoutePtr to hold ptr to our route */
  223.     if (!(rp = calloc(1,sizeof *rp))) {
  224.     printf ("out of memory\n");
  225.     goto clean;
  226.     }
  227.                 /* try to create the route */
  228.     if (!(route = MRoutePublic(sname,dname,&ri))) {
  229.     printf ("error creating route\n");
  230.     goto clean;
  231.     }
  232.  
  233.     rp->Route = route;        /* set route pointer in our list */
  234.     AddTail (&routelist,rp);    /* add to our list */
  235.     printf ("  Route %d added.\n",findpos (&routelist,rp));
  236.     return 0;
  237.  
  238. clean:
  239.     if (route) DeleteMRoute (route);
  240.     if (rp) free (rp);
  241.     return -1;
  242. }
  243.  
  244.  
  245. /* modifies a existing route based on the command line in s */
  246.  
  247. modroute(s)
  248. char *s;
  249. {
  250.     int num;
  251.     struct MRouteInfo ri;
  252.     struct MRoutePtr *rp;
  253.     struct Node *findnode();
  254.     int chanoffset,noteoffset;
  255.  
  256.     setmem (&ri,sizeof ri,0);
  257.     if (sscanf (s,"%d%x%x%d%d",&num,&ri.MsgFlags,&ri.ChanFlags,&chanoffset,¬eoffset) != 5) {
  258.     printf ("syntax error\n");
  259.     goto clean;
  260.     }
  261.     ri.ChanOffset = chanoffset;
  262.     ri.NoteOffset = noteoffset;
  263.  
  264.                 /* find our routeptr by position */
  265.     if (!(rp = (struct MRoutePtr *)findnode(&routelist,num))) {
  266.     printf ("can't find route\n");
  267.     goto clean;
  268.     }
  269.                 /* modify the route */
  270.     ModifyMRoute (rp->Route,&ri);
  271.     printf ("  Route %d modified.\n",num);
  272.     return 0;
  273.  
  274. clean:
  275.     return -1;
  276. }
  277.  
  278.  
  279. /* removes the route specifed in the command line s */
  280.  
  281. remroute(s)
  282. char *s;
  283. {
  284.     int num;
  285.     struct MRoutePtr *rp;
  286.     struct Node *findnode();
  287.  
  288.     if (sscanf (s,"%d",&num) != 1) {
  289.     printf ("syntax error\n");
  290.     goto clean;
  291.     }
  292.             /* find our route ptr by number */
  293.     if (!(rp = (struct MRoutePtr *)findnode(&routelist,num))) {
  294.     printf ("can't find route\n");
  295.     goto clean;
  296.     }
  297.             /* remove from our list */
  298.     Remove (rp);
  299.     DeleteMRoute (rp->Route);    /* delete the route */
  300.     free (rp);            /* free our route ptr */
  301.     printf ("  Route %d removed.\n",num);
  302.     return 0;
  303.  
  304. clean:
  305.     return -1;
  306. }
  307.  
  308.  
  309. /* finds a node by number */
  310.  
  311. struct Node *findnode (list,num)
  312. struct List *list;
  313. {
  314.     struct Node *node;
  315.  
  316.     for (node = list->lh_Head; node->ln_Succ; node=node->ln_Succ) {
  317.     if (!num--) return node;
  318.     }
  319.     return 0;
  320. }
  321.  
  322.  
  323. /* returns the ordinal position of a node within a list */
  324.  
  325. findpos (list,match)
  326. struct List *list;
  327. struct Node *match;
  328. {
  329.     struct Node *node;
  330.     int num;
  331.  
  332.     for (num=0,node = list->lh_Head; node->ln_Succ; num++,node=node->ln_Succ) {
  333.     if (node==match) return num;
  334.     }
  335.     return -1;
  336. }
  337.