home *** CD-ROM | disk | FTP | other *** search
/ Mods Anthology 4 / Music-AmigaModsAnthology-4of4-Psychodk.mcsteam.iso / Tools / BeBox / Ralf_Tracker_0.3_Src / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-08  |  15.6 KB  |  561 lines

  1. /* main.c */
  2.  
  3. /* plays sound/noisetracker files on Sparc, silicon graphics.
  4.  * Authors  : Liam Corner - zenith@dcs.warwick.ac.uk
  5.  *            Marc Espie - espie@ens.fr
  6.  *            Steve Haehnichen - shaehnic@ucsd.edu
  7.  *            Andrew Leahy - alf@st.nepean.uws.edu.au
  8.  *
  9.  * Usage    : tracker <filename> 
  10.  *  this version plays compressed files as well.
  11.  */
  12.  
  13. /* $Id: main.c,v 3.17 1993/11/17 15:31:16 espie Exp espie $
  14.  * $Log: main.c,v $
  15.  * Revision 3.17  1993/11/17  15:31:16  espie
  16.  * New version.
  17.  *
  18.  * Revision 3.16  1993/11/11  20:00:03  espie
  19.  * Amiga support.
  20.  *
  21.  * Revision 3.15  1993/08/04  11:55:21  espie
  22.  * Fixed upo previous song bug.
  23.  *
  24.  * Revision 3.13  1993/07/18  10:39:44  espie
  25.  * Added forking under unix. Experimental...
  26.  *
  27.  * Revision 3.11  1993/05/09  14:06:03  espie
  28.  * Fixed up bug with mix option no longer working.
  29.  *
  30.  * Revision 3.10  1993/04/25  15:13:36  espie
  31.  * Force new version.
  32.  *
  33.  * Revision 3.9  1993/01/15  14:00:28  espie
  34.  * Added bg/fg test.
  35.  *
  36.  * Revision 3.7  1992/12/03  15:00:50  espie
  37.  * restore stty.
  38.  *
  39.  * Revision 3.5  1992/11/24  10:51:19  espie
  40.  * Added loads of new options.
  41.  *
  42.  * Revision 3.3  1992/11/22  17:20:01  espie
  43.  * Augmented usage.
  44.  *
  45.  * Revision 3.2  1992/11/20  14:53:32  espie
  46.  * Added finetune.
  47.  *
  48.  * Revision 3.1  1992/11/19  20:44:47  espie
  49.  * Protracker commands.
  50.  *
  51.  * Revision 3.0  1992/11/18  16:08:05  espie
  52.  * New release.
  53.  *
  54.  * Revision 2.20  1992/11/17  17:06:25  espie
  55.  * Added PREVIOUS_SONG handling ???
  56.  * Use streamio for new interface (obsolescent signal handlers), and
  57.  * related changes.
  58.  * Cleaned up path reader, and better signal handling.
  59.  * Support for open_file.
  60.  * Added imask.
  61.  * Use transparent decompression/path lookup through open_file/close_file.
  62.  * Added setup_audio().
  63.  * Added some frequency/oversample/stereo change on the fly.
  64.  * Necessitates rightful closing/reopening of audio.
  65.  * Added compression methods. Changed getopt.
  66.  * Separated mix/stereo stuff.
  67.  * Added transpose feature.
  68.  * Added possibility to get back to MONO for the sgi.
  69.  * Added stereo capabilities to the indigo version.
  70.  * Added recovery and reread for automatic recognition
  71.  * of old/new tracker files.
  72.  * Added two level of fault tolerancy.
  73.  * Added more rational options.
  74.  * Moved almost everything to audio and automaton.
  75.  * Structured part of the code, especially replay ``automaton''
  76.  * and setting up of effects.
  77.  *
  78.  * Revision 1.26  1991/11/17  17:09:53  espie
  79.  * Added missing prototypes.
  80.  * Some more info while loading files.
  81.  * Added FAULT env variable, FAULT resistant playing,
  82.  * for playing modules which are not quite correct.
  83.  * Serious bug: dochangespeed was not reset all the time.
  84.  * Check all these parameters, they MUST be reset for
  85.  * each new song.
  86.  * Fixed a stupid bug: when env variable LOOPING was
  87.  * undefined, we got a segv on strcmp.
  88.  * Now we just test for its existence, since this is
  89.  * about all we want...
  90.  * Bug correction: when doing arpeggio, there might not
  91.  * be a new note, so we have to save the old note value
  92.  * and do the arppeggio on that note.
  93.  * Completely added control with OVERSAMPLE and FREQUENCY.
  94.  * Added control flow.
  95.  * Added pipe decompression, so that now you can do
  96.  * str32 file.Z directly.
  97.  * stdin may go away.
  98.  * Added arpeggio.
  99.  * Added vibslide and portaslide.
  100.  * Added speed command.
  101.  * Added signal control.
  102.  * Error checking: there shouldn't be that many
  103.  * segv signals any more.
  104.  * Moved every command to commands.c.
  105.  * Added some debug code for showing the full
  106.  * sequence for a file.
  107.  * Corrected the bug in volume slide: there is
  108.  * no default value, i.e., if it is 0, it is 0,
  109.  * as stupid as it may seem.
  110.  * Added vibrato.
  111.  * Added fastskip/corrected skip.
  112.  * Modified control flow of the player till
  113.  * it looks like something reasonable (i.e.,
  114.  * the structure is more natural and reflects
  115.  * the way stuff is played actually...)
  116.  * Do not restart the sound when we change instruments
  117.  * on the fly. A bit strange, but it works that way.
  118.  * Modified main to use new data structures.
  119.  * The sound player is MUCH cleaner, it uses now
  120.  * a 3-state automaton for each voice.
  121.  * Corrected ruckus with data type of sample.
  122.  */
  123.      
  124.  
  125. #include <stdio.h>
  126. #include <signal.h>
  127. #include <stdlib.h>
  128. #include <string.h>
  129. #ifndef AMIGA
  130. //#include <malloc.h>
  131. #endif
  132.      
  133. #include "defs.h"
  134. #include "extern.h"
  135. #include "song.h"
  136. #include "pref.h"
  137.      
  138. #include "getopt.h"
  139.      
  140. LOCAL char *id = "$Id: main.c,v 3.17 1993/11/17 15:31:16 espie Exp espie $";
  141.  
  142. int pid = 0;
  143. int forked = FALSE;
  144.  
  145. #define USAGE \
  146. "[options] filename [...]\n\
  147. -help               Display usage information\n\
  148. -quiet              Print no output other than errors\n\
  149. -picky              Do not tolerate any faults (default is to ignore most)\n\
  150. -tolerant           Ignore all faults\n\
  151. -mono               Select single audio channel output\n\
  152. -stereo             Select dual audio channel output\n\
  153. -verbose            Show text representation of song\n\
  154. -repeats <count>    Number of repeats (0 is forever) (default 1)\n\
  155. -speed <speed>      Song speed.  Some songs want 60 (default 50)\n\
  156. -mix <percent>      Percent of channel mixing. (0 = spatial, 100 = mono)\n\
  157. -new -old -both     Select default reading type (default is -both)\n\
  158. -frequency <freq>   Set playback frequency in Hz\n\
  159. -oversample <times> Set oversampling factor\n\
  160. -transpose <n>      Transpose all notes up\n\
  161. -show               Show what's going on\n\
  162. -sync               Try to synch audio output with display\n\
  163. \n\
  164. RunTime:\n\
  165. r       restart current song\n\
  166. e,x     exit program\n\
  167. n       next song\n\
  168. p       previous song (experimental)\n\
  169. >       fast forward\n\
  170. <       rewind\n\
  171. S       NTSC tempo\t s\tPAL tempo\n"
  172.  
  173. /* Command-line options. */
  174. LOCAL struct long_option long_options[] =
  175. {
  176.   {"help",              0, 'H'},
  177.   {"quiet",             0, 'Q'}, 
  178.   {"picky",             0, 'P'},
  179.   {"tolerant",          0, 'L'},
  180.   {"new",               0, 'N'},
  181.   {"old",               0, 'O'},
  182.   {"both",              0, 'B'},
  183.   {"mono",              0, 'M'},
  184.   {"stereo",            0, 'S'},
  185.   {"verbose",           0, 'V'},
  186.   {"frequency",         1, 'f'},
  187.   {"oversample",        1, 'o'},
  188.   {"transpose",         1, 't'},
  189.   {"repeats",           1, 'r'},
  190.   {"speed",             1, 's'},
  191.   {"mix",               1, 'm'},
  192.   {"start",             1, 'X'},
  193.   {"cut",               1, '-'},
  194.   {"add",               1, '+'},
  195.   {"show",              0, 'v'},
  196.   {"sync",              0, '='},
  197.   {0,                   0,  0 }
  198. };
  199.  
  200.  
  201.  
  202. //**********************************************************************************
  203. //**********************************************************************************
  204. //**********************************************************************************
  205. // prototypes for functions that are exported
  206. void setup_play_track(long freq, int stereo);
  207. void close_play_track(void);
  208. void play_track(char *filename);
  209.  
  210. //**********************************************************************************
  211. //**********************************************************************************
  212. //**********************************************************************************
  213. // the external function to call when the tracker wants to exit
  214. // (WARNING : these flags are obsoletes and must be removed -- must not be used)
  215. void (*gBeAudioExit)(void) = NULL;
  216.  
  217. // a flag set before main is called to tell it to random file playing
  218. int gBeAudioRandomFile = TRUE;
  219.  
  220. // a flag set by the app to go next module or to quit
  221. int gBeAudioNextModule = FALSE;
  222. int gBeAudioQuitModule = FALSE;
  223.  
  224.  
  225.  
  226. //**********************************************************************************
  227. struct SSongName
  228. {
  229.     char *name;
  230.     struct SSongName *next;
  231. };
  232.  
  233. struct SSongName *gSongNameRoot = NULL;
  234. struct SSongName *gSongNameCurrent = NULL;
  235. long int gNumberOfSongName = 0;
  236.  
  237. //**********************************************************************************
  238. void addSongName(char *name)
  239. //**********************************************************************************
  240. {
  241.     struct SSongName *cell = (struct SSongName *)malloc(sizeof(struct SSongName));
  242.     struct SSongName *p = gSongNameRoot;
  243.     long int index = gNumberOfSongName;
  244.  
  245.     cell->name = name;
  246.     cell->next = NULL;
  247.  
  248.     if (gBeAudioRandomFile) index = rand() % gNumberOfSongName;
  249.     if (index > 0)
  250.     {
  251.         long int count = 0;
  252.         //printf("adding song %s at index %d\n", name, index);
  253.         while(p && p->next && (count++ < index)) p = p->next;
  254.         if (p)
  255.         {
  256.             cell->next = p;
  257.             p->next = cell;
  258.             gNumberOfSongName++;
  259.             return;
  260.         }
  261.     }
  262.  
  263.     //printf("adding song %s as root\n", name);
  264.     if (gBeAudioRandomFile) srand(time(NULL));
  265.     cell->next = gSongNameRoot;
  266.     gSongNameCurrent = gSongNameRoot = cell;
  267.     gNumberOfSongName++;
  268.  
  269.     
  270. }
  271.  
  272.  
  273. //**********************************************************************************
  274. void listSongName(void)
  275. //**********************************************************************************
  276. {
  277.     struct SSongName *p = gSongNameCurrent;
  278.     while(p)
  279.     {
  280.         printf("%s", p->name);
  281.         p = p->next;
  282.     }
  283. }
  284.  
  285.  
  286. //**********************************************************************************
  287. struct SSongName * getSongName(void)
  288. //**********************************************************************************
  289. {
  290.     struct SSongName *p = gSongNameCurrent;
  291.     if (p) gSongNameCurrent = gSongNameCurrent->next;
  292.     return p;
  293. }
  294.  
  295. //**********************************************************************************
  296. void audioExit(long code)
  297. //**********************************************************************************
  298. {
  299.     if (gBeAudioExit) gBeAudioExit();
  300.     else exit(code);
  301. }
  302.  
  303. //**********************************************************************************
  304. /* global variable to catch various types of errors
  305.  * and achieve the desired flow of control
  306.  */
  307. int error;
  308.  
  309. //**********************************************************************************
  310. LOCAL int optvalue(def)
  311. int def;
  312.     {
  313.     int d;
  314.         if (sscanf(optarg, "%d", &d) == 1)
  315.             return d;
  316.         else
  317.             {
  318.             optind--;
  319.             return def;
  320.             }
  321.     }
  322.  
  323. //**********************************************************************************
  324. void end_all()
  325.     {
  326.     if (run_in_fg())
  327.         printf("\n");
  328.     do_close_audio();
  329.     sane_tty();
  330.     audioExit(0);
  331.     }
  332.  
  333. //**********************************************************************************
  334. LOCAL struct song *do_read_song(name, type)
  335. char *name;
  336. int type;
  337.     {
  338.     struct song *song;
  339.     FILE *file;
  340.  
  341.     if (run_in_fg())
  342.         fflush(stdout); 
  343.  
  344.     file = open_file(name, "r", getenv("MODPATH"));
  345.     if (!file)
  346.         return NULL;
  347.     song = read_song(file, type); 
  348.     close_file(file);
  349.     return song;
  350.     }
  351.  
  352.  
  353.  
  354. //**********************************************************************************
  355. int old_tracker_main(argc, argv)
  356. int argc;
  357. char **argv;
  358.     {
  359.     int ask_freq;
  360.     int oversample;
  361.     int stereo;
  362.     int start;
  363.     int transpose;
  364.  
  365.  
  366.     struct pref pref;
  367.     struct song *song;
  368.     BOOL *is_song;
  369.     int c;
  370.     int i;
  371.     int default_type;
  372.  
  373.  
  374.     is_song = (BOOL *)malloc(sizeof(BOOL) * argc);
  375.     if (!is_song)
  376.         end_all();
  377.  
  378.     for (i = 0; i < argc; i++)
  379.         is_song[i] = FALSE;            /* For termination */
  380.  
  381.     start = 0;
  382.     pref.imask = 0;
  383.     pref.bcdvol = 0;
  384.     pref.dump_song = FALSE;
  385.     show = FALSE;
  386.     pref.sync = FALSE;
  387.  
  388.  
  389.     if (argc == 1)
  390.         {
  391.         fprintf(stderr, "Usage: %s %s", argv[0], USAGE);
  392.         end_all();
  393.         }
  394.  
  395.     ask_freq = read_env("FREQUENCY", 0);
  396.     oversample = read_env("OVERSAMPLE", 1);
  397.     transpose = read_env("TRANSPOSE", 0);
  398.     stereo = !getenv("MONO");
  399.     set_mix(30);
  400.  
  401.     create_notes_table();
  402.  
  403.         /* check the command name for default reading type */
  404.  
  405.     default_type = BOTH;
  406.  
  407.     pref.type = default_type;
  408.     pref.repeats = 1;
  409.     pref.speed = 50;
  410.     pref.tolerate = 1;
  411.  
  412.     for (optind = 1; optind < argc; optind++)
  413.         {
  414.         while ((c = getopt(argc, argv, long_options))
  415.                 != EOF)
  416.             switch(c)
  417.                 {
  418.             case '-':
  419.                 if (strcmp(optarg, "all") == 0)
  420.                     pref.imask = ~0;
  421.                 else
  422.                     pref.imask |= 1L << optvalue(0);
  423.                 break;
  424.             case '+':
  425.                 if (strcmp(optarg, "all") == 0)
  426.                     pref.imask = 0;
  427.                 else
  428.                     pref.imask &= ~ (1L << optvalue(0));
  429.                 break;
  430.             case 'O':   /* old tracker type */
  431.                 pref.type = OLD;
  432.                 break;
  433.             case 'N':   /* new tracker type */
  434.                 pref.type = NEW;
  435.                 break;
  436.             case 'v':
  437.                 show = TRUE;
  438.                 break;
  439.             case '=':
  440.                 pref.sync = TRUE;
  441.                 break;
  442.             case 'B':   /* both tracker types */
  443.                 pref.type = BOTH;
  444.                 break;
  445.             case 'r':   /* number of repeats */
  446.                 pref.repeats = optvalue(0);
  447.                 break;
  448.             case 's':   /* speed */
  449.                 pref.speed = optvalue(50);
  450.                 break;
  451.             case 'M':   /* MONO */
  452.                 stereo = 0;
  453.                 break;
  454.             case 'S':   /* STEREO */
  455.                 stereo = 1;
  456.                 break;
  457.             case 'o':   /* oversample */
  458.                 oversample = optvalue(1);
  459.                 break;
  460.             case 'f':   /* frequency */
  461.                 ask_freq = optvalue(0);
  462.                 break;
  463.             case 't':   /* transpose */
  464.                 transpose = optvalue(0);
  465.                 break;
  466.             case 'P':
  467.                 pref.tolerate = 0;
  468.                 break;
  469.             case 'L':
  470.                 pref.tolerate = 2;
  471.                 break;
  472.             case 'm':   /* % of channel mix. 
  473.                          * 0->full stereo, 100->mono */
  474.                 set_mix(optvalue(30));
  475.                 break;
  476.             case 'X':
  477.                 start = optvalue(0);
  478.                 break;
  479.             case 'H':   /* template */
  480.                 fprintf(stderr, "Usage: %s %s", argv[0], USAGE);
  481.                 end_all();
  482.             case 'V':
  483.                 pref.dump_song = TRUE;
  484.                 }
  485.  
  486.         if (optind < argc) addSongName(argv[optind]);
  487.         } // for
  488.  
  489.         while(!gBeAudioQuitModule)
  490.         {
  491.             struct SSongName * cell = getSongName();
  492.             if (!cell) audioExit(0);
  493.  
  494.             printf("Module : %s\n", cell->name);
  495.  
  496.             song = do_read_song(cell->name, NEW);
  497.             if (!song && error != NEXT_SONG) song = do_read_song(cell->name, OLD);
  498.             if (!song) audioExit(0);
  499.       if (pref.dump_song) dump_song(song); 
  500.       transpose_song(song, transpose);
  501.       setup_audio(ask_freq, stereo, oversample, pref.sync);
  502.       play_song(song, &pref, start);
  503.       release_song(song);
  504.       printf("\n");
  505.         }
  506.  
  507.          audioExit(0);
  508.     return 0;
  509.     /* NOT REACHED */
  510. }
  511.  
  512.  
  513. //**********************************************************************************
  514. void setup_play_track(long freq, int stereo)
  515. //**********************************************************************************
  516. {
  517.     setup_audio(freq, stereo, TRUE, FALSE);
  518. }
  519.  
  520. //**********************************************************************************
  521. void close_play_track(void)
  522. //**********************************************************************************
  523. {
  524.     do_close_audio();
  525. }
  526.  
  527.  
  528. //**********************************************************************************
  529. void play_track(char *filename)
  530. //**********************************************************************************
  531. {
  532.     struct song *song;
  533.     struct pref pref;
  534.  
  535.     if (!filename) return;
  536.  
  537.     pref.imask = 0;
  538.     pref.bcdvol = 0;
  539.     pref.dump_song = FALSE;
  540.     pref.sync = FALSE;
  541.     pref.type = BOTH;
  542.     pref.repeats = 1;
  543.     pref.speed = 50;
  544.     pref.tolerate = 1;
  545.  
  546.     set_mix(30);
  547.     create_notes_table();
  548.  
  549.     song = do_read_song(filename, NEW);
  550.     if (!song && error != NEXT_SONG) song = do_read_song(filename, OLD);
  551.     if (song)
  552.     {
  553.         transpose_song(song, FALSE);
  554.         setup_audio(0, TRUE, TRUE, FALSE);
  555.         play_song(song, &pref, 0);
  556.         release_song(song);
  557.     }
  558. }
  559.  
  560.  
  561.