home *** CD-ROM | disk | FTP | other *** search
/ Audio 4.94 - Over 11,000 Files / audio-11000.iso / amiga / midi / obrst103.lha / OberSuite-1.03 / SourceCode / obget.c < prev    next >
C/C++ Source or Header  |  1993-01-23  |  8KB  |  315 lines

  1. /**************************************************************************
  2. * obget.c:    Main program for ObGet.
  3. *        Request patch data from the Oberheim synth and store it in
  4. *         a disk file.
  5. *        A part of OberSuite for the Commodore Amiga.
  6. *
  7. * Author:    Daniel Barrett, barrett@cs.umass.edu.
  8. * Version:    1.0.
  9. * Copyright:    None!  This program is in the Public Domain.
  10. *        Please share it with others.
  11. ***************************************************************************/
  12.  
  13. #include "decl.h"
  14. #include "obget.h"
  15.  
  16. char *version = "$VER: ObGet "  VERSION " " VERDATE;
  17.     
  18. /***************************************************************************
  19. * The main program.
  20. ***************************************************************************/
  21.  
  22. main(argc, argv)
  23. int argc; char *argv[];
  24. {
  25.     Enable_Abort = 0;            /* Disable ^C aborts. */
  26.     strcpy(programName, BaseName(argv[0]));    /* Global variable. */
  27.     thePrintStyle    = VERBOSE;        /* Global variable. */
  28.     overwriteAll    = FALSE;        /* Global variable. */
  29.  
  30.     if (argc == 1)
  31.     {
  32.         ShortUsageMsg();
  33.         BegForUsage();
  34.     }
  35.     else if ((argc == 2) && (!strcmp(argv[1], "?")))
  36.         DetailedUsage();
  37.     else if (argc < 3)
  38.         ErrorMsg(ERROR_NUMARGS);
  39.     else if (!HandleOptions(argc, argv))
  40.         BegForUsage();
  41.     else if (optind != argc-2)
  42.         ErrorMsg(ERROR_NUMARGS);
  43.     else
  44.         ObGet(argv[optind], argv[optind+1]);
  45.  
  46.     exit(0);
  47. }
  48.  
  49. /*
  50.  * Request the given patch (specified by patchString) and store it in the
  51.  * given file.
  52.  */
  53.  
  54. void ObGet(char *patchString, char *filename)
  55. {
  56.     PATCHINFO pi;
  57.  
  58.     InitPatchInfo(&pi);
  59.  
  60.     pi.source = PI_SOURCE_MIDI;    
  61.     if (!SerialSetup())
  62.         return;
  63.  
  64.     if (BreakUp(patchString, &pi))
  65.     {
  66.         if (!overwriteAll && DontOverwriteExistingFile(filename))
  67.             ;
  68.         else if (CtrlcCheck())
  69.             ErrorMsg(ERROR_CTRLC);
  70.         else if (!TransmitPatchInfo(&pi, filename))
  71.             ErrorMsg(ERROR_FAILED);
  72.         else
  73.             ;
  74.     }
  75.  
  76.     FreePatchInfo(&pi);
  77.     SerialShutdown();
  78. }
  79.  
  80.  
  81. /*
  82.  * Given a patch string like "s23" or "m95", break it into its components
  83.  * ('s' or 'm', and the optional integer patch number).
  84.  * Store these components in the PATCHINFO structure.
  85.  * Return TRUE on success (else FALSE).
  86.  */
  87.  
  88. BOOL BreakUp(char *patchString, PATCHINFO *pi)
  89. {
  90.     if ((!patchString) || (patchString[0] == '\0'))
  91.     {
  92.         ErrorMsg(ERROR_PATCHTYPE);
  93.         return(FALSE);
  94.     }
  95.     else if (!FigureOutMode(pi, patchString[0]))
  96.         return(FALSE);
  97.     else if (!FigureOutPatchNumber(pi, patchString+1))
  98.         return(FALSE);
  99.     else
  100.         return(TRUE);
  101. }
  102.  
  103.  
  104. /*
  105.  * The modeLetter must be either MODE_SINGLE or MODE_MULTI.
  106.  * From the letter, deduce the mode and mode name (string).
  107.  * Return TRUE on success (else FALSE).
  108.  */
  109.  
  110. BOOL FigureOutMode(PATCHINFO *pi, char modeLetter)
  111. {
  112.     if (toupper(modeLetter) == LETTER_SINGLE)
  113.     {
  114.         pi->mode = MODE_SINGLE;
  115.         strcpy(pi->modeName, NAME_SINGLE);
  116.     }
  117.     else if (toupper(modeLetter) == LETTER_MULTI)
  118.     {
  119.         pi->mode = MODE_MULTI;
  120.         strcpy(pi->modeName, NAME_MULTI);
  121.     }
  122.     else
  123.     {
  124.         ErrorMsg(ERROR_PATCHTYPE);
  125.         return(FALSE);
  126.     }
  127.  
  128.     return(TRUE);
  129. }
  130.  
  131.  
  132. /*
  133.  * The string numString must be either empty (implying that all patches
  134.  * should be transferred) or an integer between FIRST_PATCH and LAST_PATCH.
  135.  * Anything else is illegal.
  136.  * Store the patch number in the patchNum field of the PATCHINFO struct, and
  137.  *  put a "1" in the numPatches field.
  138.  * If the string is empty, store ALL_PATCHES_NUM in the patchNum field,
  139.  *  and put ALL_PATCHES_NUM in the numPatches field.
  140.  */
  141.  
  142. BOOL FigureOutPatchNumber(PATCHINFO *pi, char *numString)
  143. {
  144.     if (!numString)
  145.     {
  146.         ErrorMsg(ERROR_PATCHNUM);
  147.         return(FALSE);
  148.     }
  149.     else if (!(*numString))
  150.     {
  151.         pi->patchNum   = ALL_PATCHES_NUM;
  152.         pi->numPatches = ALL_PATCHES_NUM;
  153.     }
  154.     else if (!AllDigits(numString))
  155.     {
  156.         ErrorMsg(ERROR_PATCHNUM);
  157.         return(FALSE);
  158.     }
  159.     else
  160.     {
  161.         pi->patchNum = atoi(numString);
  162.         if (Between(pi->patchNum, FIRST_PATCH, LAST_PATCH))
  163.             pi->numPatches = 1L;
  164.         else if (pi->patchNum == ALL_PATCHES_NUM)
  165.             pi->numPatches = (long)ALL_PATCHES_NUM;
  166.         else
  167.         {
  168.             ErrorMsg(ERROR_PATCHNUM);
  169.             return(FALSE);
  170.         }
  171.     }
  172.     return(TRUE);
  173. }
  174.  
  175.  
  176. /***************************************************************************
  177. * Handle the command-line options.
  178. ***************************************************************************/
  179.  
  180. BOOL HandleOptions(int argc, char *argv[])
  181. {
  182.     int c;
  183.     short printed = 0;    /* How many print options were chosen? */
  184.  
  185.     while ((c = getopt(argc, argv, options)) != EOF)
  186.     {
  187.         switch (c)
  188.         {
  189.             case OPT_SILENT:
  190.                 thePrintStyle = SILENT;
  191.                 printed++;
  192.                 break;
  193.             case OPT_VERBOSE:
  194.                 thePrintStyle = VERBOSE;
  195.                 printed++;
  196.                 break;
  197.             case OPT_DEADQUIET:
  198.                 thePrintStyle = DEADQUIET;
  199.                 printed++;
  200.                 break;
  201.             case OPT_OVERWRITE:
  202.                 overwriteAll = TRUE;
  203.                 break;
  204.             default:
  205.                 return(FALSE);
  206.         }
  207.     }
  208.  
  209.     if (printed > 1)        /* Can't choose 2 print options. */
  210.         ErrorMsg(ERROR_TWOPRINTS);
  211.  
  212.     return(printed <= 1);
  213. }
  214.  
  215. /***************************************************************************
  216. * Transmit the PATCHINFO structure data to MIDI.
  217. ***************************************************************************/
  218.  
  219. BOOL TransmitPatchInfo(PATCHINFO *pi, char *filename)
  220. {
  221.     BOOL result = TRUE;
  222.  
  223.     /* This is still a hack, but better than before (slightly).
  224.      * We set rightSize to be >= than what we'll need, based on
  225.      * the mode.  This wastes RAM for Xpander multi-patches, because
  226.      * Matrix-12 multi-patch dumps are almost 2 times larger.
  227.      * Note that in FigureOutInstrument(), we finally set rightSize
  228.      * to its proper value.  Take this into consideration when we
  229.      * finally fix this hack.
  230.     */
  231.  
  232.     pi->rightSize = (pi->mode == MODE_MULTI)
  233.             ? MATRIX12_MULTI_SIZE
  234.             : LARGEST_OBERHEIM_PATCHSIZE;
  235.  
  236.     if (! (result = AllocPatchInfo(pi)) )
  237.         ErrorMsg(ERROR_MALLOC);
  238.     else if (! (result = GetPatchFromMidi(pi)) )
  239.         ErrorMsg(ERROR_GETFAILED);
  240.     else if (! (result = PutPatchToFile(pi, filename)) )
  241.         ErrorMsg(ERROR_PUTFAILED_SAVE);
  242.  
  243.     return(result);
  244. }
  245.  
  246.     
  247. /***************************************************************************
  248. * Usage information.
  249. ***************************************************************************/
  250.  
  251.  
  252. void ShortUsageMsg(void)
  253. {
  254.     if (!ERR_OUTPUT_ALLOWED)
  255.         return;
  256.  
  257.     fprintf(stderr, "Usage: %s [options] PATCH filename\n", programName);
  258. }
  259.  
  260.  
  261. void UsageMsg(void)
  262. {
  263.     if (!ERR_OUTPUT_ALLOWED)
  264.         return;
  265.  
  266.     fprintf(stderr, "%s grabs Xpander/Matrix-12 patch data"
  267.             " and saves it in a file.\n",
  268.         programName);
  269.  
  270.     ShortUsageMsg();
  271.  
  272.     fprintf(stderr, "\nLegal options are:\n");
  273.     fprintf(stderr,
  274.         "\t-%c:\tOverwrite existing files without asking permission.\n",
  275.         OPT_OVERWRITE);
  276.     fprintf(stderr, "\t-%c:\tQuiet output; error messages only.\n",
  277.         OPT_SILENT);
  278.     fprintf(stderr, "\t-%c:\tNo output; not even error messages.\n",
  279.         OPT_DEADQUIET);
  280.     fprintf(stderr, "\t-%c:\tLong output.       (DEFAULT)\n",
  281.         OPT_VERBOSE);
  282.  
  283.     fprintf(stderr, "\n\"PATCH\" may be any of the following forms:\n");
  284.     fprintf(stderr,    "   One single patch:\t");
  285.     fprintf(stderr, "The letter %c followed by a number between %d-%d.\n",
  286.             LETTER_SINGLE, FIRST_PATCH, LAST_PATCH);
  287.     fprintf(stderr,    "   One multi patch:\t");
  288.     fprintf(stderr, "The letter %c followed by a number between %d-%d.\n",
  289.             LETTER_MULTI, FIRST_PATCH, LAST_PATCH);
  290.  
  291.     fprintf(stderr,
  292.         "   All single patches:\tThe letter %c, or %c%d.\n",
  293.         LETTER_SINGLE, LETTER_SINGLE, ALL_PATCHES_NUM);
  294.     fprintf(stderr,
  295.         "   All multi patches:\tThe letter %c, or %c%d.\n",
  296.         LETTER_MULTI, LETTER_MULTI, ALL_PATCHES_NUM);
  297.  
  298.     fprintf(stderr,
  299.         "Upper and lower case are equivalent for '%c' and '%c'.\n",
  300.         LETTER_SINGLE, LETTER_MULTI);
  301.  
  302.     fprintf(stderr, "Examples:\n");
  303.     fprintf(stderr, "\t%s %c34 MyFile\n", programName, LETTER_SINGLE);
  304.     fprintf(stderr, "\t%s %c MyFile\n", programName,
  305.         tolower(LETTER_MULTI));
  306.  
  307. }
  308.  
  309.  
  310. char *Version(void)
  311. {
  312.     static char v[] = VERSION;
  313.     return(v);
  314. }
  315.