home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / MM1 / SOUNDUTILS / mm1_tracker.lzh / TRACKER4.6 / Amiga / main.c < prev    next >
C/C++ Source or Header  |  1994-11-24  |  11KB  |  429 lines

  1. /* amiga/main.c 
  2.     vi:ts=3 sw=3:
  3.  */
  4.  
  5. /* plays sound/noisetracker files on Sparc, silicon graphics.
  6.  * Authors  : Liam Corner - zenith@dcs.warwick.ac.uk
  7.  *            Marc Espie - espie@ens.fr
  8.  *            Steve Haehnichen - shaehnic@ucsd.edu
  9.  *            Andrew Leahy - alf@st.nepean.uws.edu.au
  10.  *
  11.  * Usage    : tracker <filename> 
  12.  *  this version plays compressed files as well.
  13.  *    Modified version of the standard main.c
  14.  */
  15.  
  16. /* $Id: main.c,v 1.14 1994/06/22 21:54:12 Espie Exp Espie $
  17.  * $Log: main.c,v $
  18.  * Revision 1.12  1994/06/22  00:24:51  Espie
  19.  * Added wb2cli, workbench support !
  20.  * File requester !
  21.  * Uncentralized event handling using event management functions.
  22.  * Suppressed calls to run_in_fg().
  23.  * Added check for / in song names to display something sensible
  24.  * in the title bar...
  25.  * Corrected minor previous song bug.
  26.  * Suppressed spurious code.
  27.  * Added CUT/ADD keywords.
  28.  * Branching to amiga version from unix version 3.20
  29.  */
  30.      
  31.  
  32. #include <exec/types.h>
  33. #include <exec/memory.h>
  34. #include <proto/dos.h>
  35. #include <proto/exec.h>
  36. #include <dos/dosasl.h>
  37. #include <dos/dosextens.h>
  38. #include <exec/libraries.h>
  39.      
  40. #include "defs.h"
  41.  
  42. #include <stdio.h>
  43. #include <signal.h>
  44. #include <stdlib.h>
  45. #include <string.h>
  46. #ifdef MALLOC_NOT_IN_STDLIB
  47. #include <malloc.h>
  48. #endif
  49.  
  50. #include "song.h"
  51. #include "extern.h"
  52.  
  53. #include "tags.h"
  54. #include "prefs.h"
  55. #include "amiga/amiga.h"
  56. #include "amiga/wb2cli.h"
  57.      
  58. ID("$Id: main.c,v 1.14 1994/06/22 21:54:12 Espie Exp Espie $")
  59.  
  60.  
  61. LOCAL char *amiga_version = "$VER: tracker 4.5 (21.06.94) $";
  62.  
  63. LOCAL struct MinList temp;
  64.  
  65. LOCAL void print_usage()
  66.    {
  67.    GENERIC handle;
  68.    
  69.    handle = begin_info("Usage");
  70.    info(handle, "Usage: tracker files OPTIONS");
  71.    info(handle, "HELP               Display usage information");
  72.    info(handle, "QUIET              Print no output other than errors");
  73.    info(handle, "PICKY              Do not tolerate any faults (default is to ignore most)");
  74.    info(handle, "TOLERANT           Ignore all faults");
  75.    info(handle, "VERBOSE            Show text representation of song");
  76.    info(handle, "REPEATS count      Number of repeats (0 is forever) (default 1)");
  77.    info(handle, "SPEED speed        Song speed.  Some songs want 60 (default 50)");
  78.    info(handle, "NEW/OLD/BOTH       Select default reading type (default is -both)");
  79.    info(handle, "TRANSPOSE n        Transpose notes up by n halftones");
  80.    info(handle, "SCROLL             Show notes scrolling by");
  81.    info(handle, "CUT ab1            Play all instruments except number 1 a and b");
  82.    info(handle, "ADD ab1            Play only instruments except number 1 a and b");
  83.    info(handle, "GUI                open GUI directly");
  84.    end_info(handle);
  85.    }
  86.  
  87. /* arg parser for command-line options. */
  88.  
  89. LOCAL char *template = 
  90. "FILES/M,HELP/S,QUIET/S,TOLERANT/S,PICKY/S,NEW/S,OLD/S,BOTH/S,V=VERBOSE/S,\
  91. TRANS=TRANSPOSE/K/N,R=REPEATS/K,SPEED/K/N,START/K,\
  92. CUT/K,ADD/K,SCROLL/S,GUI/S";
  93.  
  94. #define OPT_HELP 1
  95. #define OPT_QUIET 2
  96. #define OPT_TOLERANT 3
  97. #define OPT_PICKY 4
  98. #define OPT_NEW 5
  99. #define OPT_OLD 6
  100. #define OPT_BOTH 7
  101. #define OPT_VERBOSE 8
  102. #define OPT_TRANSPOSE 9
  103. #define OPT_REPEATS 10
  104. #define OPT_SPEED 11
  105. #define OPT_START 12
  106. #define OPT_CUT 13
  107. #define OPT_ADD 14
  108. #define OPT_SHOW 15
  109. #define OPT_GUI 16
  110.  
  111. LOCAL LONG args[18];
  112.  
  113. LOCAL struct RDArgs *rdargs = 0;
  114.  
  115. LOCAL void free_args()
  116.    {
  117.    if (rdargs)
  118.       FreeArgs(rdargs);
  119.    }
  120.  
  121. /* global variable to catch various types of errors
  122.  * and achieve the desired flow of control
  123.  */
  124. int error;
  125.  
  126. LOCAL struct song *do_read_song(name, type)
  127. char *name;
  128. int type;
  129.    {
  130.    struct song *song;
  131.    struct exfile *file;
  132.  
  133.    file = open_file(name, "r", getenv("MODPATH"));
  134.    if (!file)
  135.       return NULL;
  136.    song = read_song(file, type); 
  137.    close_file(file);
  138.    return song;
  139.    }
  140.  
  141. LOCAL int start;
  142. LOCAL int transpose;
  143.  
  144.  
  145. LOCAL void use_options()
  146.    {
  147.    char *s;
  148.    
  149.    if ((s = args[OPT_CUT]) || (s = args[OPT_ADD]))
  150.       {
  151.       char c;
  152.       ULONG imask = 0;
  153.       
  154.       while (c = *s++)
  155.          {
  156.          if (c >= '1' && c <= '9')
  157.             imask |= 1<< (c-'1');
  158.          else if (c >= 'A' && c <= 'Z')
  159.             imask |= 1 << (c-'A'+9);
  160.          else if (c >= 'a' && c <= 'z')
  161.             imask |= 1 << (c-'a'+9);
  162.          }
  163.       if (args[OPT_CUT])
  164.          set_pref_scalar(PREF_IMASK, imask);
  165.       else
  166.          set_pref_scalar(PREF_IMASK, ~imask);
  167.       }        
  168.    if (args[OPT_OLD])
  169.       set_pref_scalar(PREF_TYPE, OLD);
  170.    if (args[OPT_NEW])
  171.       set_pref_scalar(PREF_TYPE, NEW);
  172.    if (args[OPT_SHOW])
  173.       set_pref_scalar(PREF_SHOW, TRUE);
  174.    if (args[OPT_BOTH])
  175.       set_pref_scalar(PREF_TYPE, BOTH);
  176.    if (args[OPT_REPEATS])
  177.       set_pref_scalar(PREF_REPEATS, *((ULONG *)args[OPT_REPEATS]));
  178.    if (args[OPT_SPEED])
  179.       set_pref_scalar(PREF_SPEED, *((ULONG *)args[OPT_SPEED]));
  180.    if (args[OPT_TRANSPOSE])
  181.       transpose = *((LONG *)args[OPT_TRANSPOSE]);
  182.    if (args[OPT_PICKY])
  183.       set_pref_scalar(PREF_TOLERATE, 0);
  184.    else if (args[OPT_TOLERANT])
  185.       set_pref_scalar(PREF_TOLERATE, 0);
  186.    if (args[OPT_START])
  187.       start = *((ULONG *)args[OPT_START]);
  188.    if (args[OPT_HELP])
  189.       {
  190.       print_usage();
  191.       end_all(0);
  192.       }
  193.    if (args[OPT_VERBOSE])
  194.       set_pref_scalar(PREF_DUMP, TRUE);
  195.    }
  196.  
  197. LOCAL struct song *load_song(name)
  198. char *name;
  199.    {
  200.    struct song *song;
  201.    char *buffer;
  202.    int i, j;
  203.    
  204.    i = strlen(name);
  205.    
  206.    for (j = i; j > 0; j--)
  207.       if (name[j] == '/' || name[j] == ':')
  208.          {
  209.          j++;
  210.          break;
  211.          }
  212.    
  213.    buffer = malloc( i - j + 5);
  214.    if (buffer)
  215.       {
  216.       sprintf(buffer, "%s...", name + j);
  217.       status(buffer);
  218.       }
  219.  
  220.    switch(get_pref_scalar(PREF_TYPE))
  221.       {
  222.    case BOTH:
  223.       song = do_read_song(name, NEW);
  224.       if (song)
  225.          break;
  226.       /* FALLTHRU */
  227.    case OLD:
  228.       song = do_read_song(name, OLD);
  229.       break;
  230.       /* this is explicitly flagged as a new module,
  231.        * so we don't need to look for a signature.
  232.        */
  233.    case NEW:
  234.       song = do_read_song(name, NEW_NO_CHECK);
  235.       break;
  236.       }
  237.    if (buffer)
  238.       {
  239.       status(0);
  240.       free(buffer);
  241.       }
  242.    return song;
  243.    }
  244.  
  245.  
  246. #define PATHSIZE 250
  247.  
  248. struct MinList *expand_names(char *pat[])
  249.    {
  250.    int i;
  251.    struct AnchorPath *ap;
  252.    int error;
  253.    int total;
  254.    struct amiganame *new;
  255.    
  256.    NewList(&temp);
  257.    ap = AllocVec(sizeof(struct AnchorPath) + PATHSIZE, MEMF_CLEAR);
  258.    if (!ap)
  259.       end_all(0);
  260.    ap->ap_Strlen = PATHSIZE;
  261.    for (i = 0; pat && pat[i]; i++)
  262.       {
  263.       for (error = MatchFirst(pat[i], ap); !error; error = MatchNext(ap))
  264.          {
  265.          total = strlen(ap->ap_Buf) +1 ;
  266.          if (strcmp(ap->ap_Buf + total -6, ".info") == 0)
  267.             continue;
  268.          new = malloc(sizeof(struct amiganame) + total);
  269.          if (!new)
  270.             continue;
  271.          strcpy(new->s, ap->ap_Buf);
  272.          new->i = TRUE;
  273.             AddTail(&temp, new);
  274.          }
  275.       MatchEnd(ap);
  276.       }
  277.    FreeVec(ap);
  278.    return &temp;
  279.    }
  280.       
  281. /* add test for >=37 */
  282.  
  283. XT struct DosLibrary *DOSBase;      
  284. XT struct WBStartup *_WBenchMsg;
  285.  
  286. int main(argc, argv)
  287. int argc;
  288. char **argv;
  289.    {
  290.    struct song *song;
  291.    struct MinList *list;
  292.    struct amiganame *element, *i;
  293.  
  294.    struct tag *result;
  295.  
  296.    if (DOSBase->dl_lib.lib_Version < 37)
  297.       end_all("Need OS >= 2.04");
  298.  
  299.    start = 0;
  300.    set_pref_scalar(PREF_IMASK, 0);
  301.    set_pref_scalar(PREF_BCDVOL, 0);
  302.    set_pref_scalar(PREF_DUMP, FALSE);
  303.    set_pref_scalar(PREF_SHOW, FALSE);
  304.    set_pref_scalar(PREF_SYNC, FALSE);
  305.    set_pref_scalar(PREF_TYPE, BOTH);
  306.    set_pref_scalar(PREF_REPEATS, 1);
  307.    set_pref_scalar(PREF_SPEED, 50);
  308.    set_pref_scalar(PREF_TOLERATE, 1);
  309.  
  310.    if (argc == 1)
  311.       {
  312.       print_usage();
  313.       end_all(0);
  314.       }
  315.  
  316.    transpose = read_env("TRANSPOSE", 0);
  317.  
  318.  
  319.    if (argc > 0)     /* CLI */
  320.       {
  321.       /* check the command name for default reading type */
  322.  
  323.       rdargs = ReadArgs(template, args, 0);
  324.       if (rdargs)
  325.          at_end(free_args);
  326.       else
  327.          end_all(0);
  328.    
  329.       use_options();
  330.    
  331.       list = expand_names(args[0]);
  332.       }
  333.    else
  334.       (void)WB2CLI(_WBenchMsg, 4000, DOSBase);
  335.  
  336. again:      
  337.    if (argc == 0 || args[OPT_GUI])
  338.       {
  339.          /* force the interface to appear BEFORE the requester */
  340.       status(0);
  341.       launch_requester();
  342.       list = 0;
  343.       forever
  344.          {
  345.          result = get_ui();
  346.          while (result = get_tag(result))
  347.             {
  348.                /* forgotten from previous versions ! */
  349.             if (result->type == UI_QUIT)
  350.                end_all(0);
  351.             if (result->type == UI_LOAD_SONG)
  352.                {
  353.                i = (struct amiganame *)result->data.pointer;
  354.                if (!i)
  355.                   end_all(0);
  356.                temp.mlh_Tail = 0;
  357.                temp.mlh_Head = i;
  358.                temp.mlh_TailPred = i->n.mln_Pred;
  359.                i->n.mln_Pred->mln_Succ = &(temp.mlh_Tail);
  360.                i->n.mln_Pred = &temp;
  361.                list = &temp;
  362.                break;
  363.                }
  364.             }
  365.          if (list)
  366.             break;
  367.          await_events();
  368.          }
  369.       }
  370.       
  371.    for (element = list->mlh_Head; element->n.mln_Succ; element = element->n.mln_Succ)
  372.       {
  373.       if (!element->i)
  374.          continue;
  375.       song = load_song(element->s);   
  376.       if (song)
  377.          element->i = TRUE;
  378.       else
  379.          {
  380.          char buffer[150];
  381.  
  382.          sprintf(buffer, "%s is not a song", element->s);
  383.          notice(buffer);
  384.          element->i = FALSE;
  385.          continue;
  386.          }
  387. play_on:
  388.       if (get_pref_scalar(PREF_DUMP))
  389.          dump_song(song); 
  390.       transpose_song(song, transpose);
  391.       setup_audio(0, 1, 1);   /* doesn't really matter on the amiga */
  392.       set_busy_pointer(FALSE);
  393.       result = play_song(song, start);
  394.       set_busy_pointer(TRUE);
  395.       release_song(song);
  396.       while (result = get_tag(result))
  397.          {
  398.          switch (result->type)
  399.             {
  400.          case PLAY_PREVIOUS_SONG:
  401.             for (element = element->n.mln_Pred; element->n.mln_Pred; 
  402.                element = element->n.mln_Pred)
  403.                if (element->i)
  404.                   {
  405.                   song = load_song(element->s);
  406.                   goto play_on;
  407.                   }
  408.             break;
  409.          case PLAY_LOAD_SONG:
  410.                /* splice play load song result into list */
  411.             i = (struct amiganame *)result->data.pointer;
  412.             element->n.mln_Succ->mln_Pred = i->n.mln_Pred;
  413.             i->n.mln_Pred->mln_Succ = element->n.mln_Succ;
  414.             element->n.mln_Succ = i;
  415.             i->n.mln_Pred = element;
  416.          default:
  417.             break;
  418.             }
  419.          result++;
  420.          }
  421.             
  422.       }
  423.    if (argc == 0 || args[OPT_GUI])
  424.       goto again;
  425.    end_all(0);
  426.    /* NOTREACHED */
  427.    }
  428.  
  429.