home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / sound / midi / midilb20.lha / r.c < prev    next >
C/C++ Source or Header  |  1988-10-23  |  8KB  |  342 lines

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