home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 February / PCO_0299.ISO / filesbbs / linux / mikmod-3.000 / mikmod-3 / mikmod-3.1.2 / mikmod / mikmod.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-07  |  16.6 KB  |  692 lines

  1. /*  MikMod example player
  2.     (c) 1998 Miodrag Vallat and others - see file AUTHORS for complete list
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /*==============================================================================
  20.  
  21.   $Id: mikmod.c,v 1.42 1998/12/07 06:01:25 miod Exp $
  22.  
  23.   Module player example of MikMod
  24.  
  25. ==============================================================================*/
  26.  
  27. #ifdef HAVE_CONFIG_H
  28. #include "config.h"
  29. #endif
  30.  
  31. #ifdef HAVE_UNISTD_H
  32. #include <unistd.h>
  33. #endif
  34. #include <ctype.h>
  35. #ifdef HAVE_GETOPT_LONG_ONLY
  36. #include <getopt.h>
  37. #else
  38. #include "../extra/getopt.h"
  39. #endif
  40. #ifdef HAVE_LIMITS_H
  41. #include <limits.h>
  42. #endif
  43. #ifdef __EMX__
  44. #define PATH_MAX _POSIX_PATH_MAX
  45. #endif
  46. #include <signal.h>
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <string.h>
  50. #ifdef NEED_USLEEP
  51. void usleep(unsigned long);
  52. #endif
  53. #if defined(__OS2__)||defined(__EMX__)
  54. #define INCL_DOS
  55. #define INCL_KBD
  56. #include <os2.h>
  57. #endif
  58.  
  59. #if !defined(__OS2__)&&!defined(__EMX__)
  60. #ifdef HAVE_NCURSES_H
  61. #include <ncurses.h>
  62. #else
  63. #include <curses.h>
  64. #endif
  65. #else
  66. #include <conio.h>
  67. #endif
  68.  
  69. #include <mikmod.h>
  70.  
  71. #include "player.h"
  72.  
  73. #ifdef CPUTIME_SNAGGER
  74. #if defined(__FreeBSD__)||defined(__NetBSD__)||defined(__OpenBSD__)
  75. #ifdef HAVE_SYS_TIME_H
  76. #include <sys/time.h>
  77. #endif
  78. #include <sys/resource.h>
  79. #include <sys/types.h>
  80. #ifdef __FreeBSD__
  81. #include <sys/rtprio.h>
  82. #endif
  83. #endif
  84. #if defined(__linux)
  85. #ifdef BROKEN_SCHED
  86. #define _P __P
  87. #endif
  88. #include <sched.h>
  89. #endif
  90. #if defined(__OS2__)||defined(__EMX__)
  91. #define INCL_DOSPROCESS
  92. #include <os2.h>
  93. #endif
  94. #endif
  95.  
  96. PLAYLIST playlist;
  97. #ifdef CPUTIME_SNAGGER
  98. #ifdef __FreeBSD__
  99. struct rtprio rtp;
  100. #endif
  101. #endif
  102.  
  103. char helptext[]=
  104. "\nAvailable switches:\n"
  105. "-c[urious]              Look for hidden patterns in module.\n"
  106. "-d[river] n             Use nth driver for output. Default is 0 (autodetect).\n"
  107. "-8, -ei[ghtbits]        Force 8 bit output.\n"
  108. "-F, -fa[deout]          Force volume fade at the end of the module.\n"
  109. "-f[requency] nnnnn      Sets mixing frequency. Default is 44100.\n"
  110. #ifndef VIRTCH2
  111. "-i[nterpolate]          Use interpolate mixing.\n"
  112. #endif
  113. "-k, -o[nce]             Play files only once.\n"
  114. "-m[ono]                 Force mono output.\n"
  115. "-n[oloops]              Disables in-module loops.\n"
  116. "-p, -pa[nning] nn       Sets default panning (0=left,255=right,128=center).\n"
  117. "-pl[aylist] file        Use playlist.\n"
  118. "-x, -pr[otracker]       Disable extended protracker effects.\n"
  119. "-q[uiet]                Quiet mode, no interface, displays only errors.\n"
  120. "-ra[ndom]               Random file play.\n"
  121. #ifdef CPUTIME_SNAGGER
  122. "-s, -ren[ice]           Renice to -20 (more scheduling priority).\n"
  123. #ifndef __OpenBSD__
  124. "-S, -rea[ltime]         Get realtime priority (will hog CPU power).\n"
  125. #endif
  126. #endif
  127. "-r[epeat]               Repeat module after it's finished.\n"
  128. "-e, -rev[erb] nn        Set reverb amount. Default is 0 (none), max is 15.\n"
  129. "-su[rround]             Use surround mixing.\n"
  130. "-te[rse]                Terse output : status line only.\n"
  131. "-t[olerant]             Tolerant mode : don't halt on file access errors.\n"
  132. "-v[olume] nn            Sets volume from 0% (silence) to 100%. Default is 100%.\n"
  133. "\n"
  134. "-l, -inf[ormation]      List all available drivers and module loaders.\n"
  135. "\n"
  136. "-ve[rsion]              Display MikMod version.\n"
  137. "-h[elp]                 Display this help screen.\n";
  138.  
  139. /* Long options definition */
  140. struct option options[]={
  141.     {"curious",        no_argument,        NULL,'c'},
  142.     {"driver",        required_argument,    NULL,'d'},
  143.     {"eightbits",    no_argument,        NULL,'8'},
  144.     {"fadeout",        no_argument,        NULL,'F'},
  145.     {"frequency",    required_argument,    NULL,'f'},
  146.     {"interpolate",    no_argument,        NULL,'i'},
  147.     {"mono",        no_argument,        NULL,'m'},
  148.     {"noloops",        no_argument,        NULL,'n'},
  149.     {"once",        no_argument,        NULL,'k'},
  150.     {"panning",        optional_argument,    NULL,'p'},
  151.     {"playlist",    required_argument,    NULL,  2},    /* pl */
  152.     {"protracker",    no_argument,        NULL,'x'},
  153.     {"quiet",        no_argument,        NULL,'q'},
  154.     {"random",        no_argument,        NULL,  1},    /* rp */
  155.     {"realtime",    no_argument,        NULL,'S'},
  156.     {"renice",        no_argument,        NULL,'s'},
  157.     {"repeat",        no_argument,        NULL,'r'},
  158.     {"reverb",        required_argument,    NULL,'e'},
  159.     {"surround",    no_argument,        NULL,  4},
  160.     {"terse",        no_argument,        NULL,  3},  /* so */
  161.     {"tolerant",    no_argument,        NULL,'t'},
  162.     {"volume",        required_argument,    NULL,'v'},
  163.     {"information",    no_argument,        NULL,'l'},
  164.     {"version",        no_argument,        NULL,'V'},
  165.     {"help",        no_argument,        NULL,'h'},
  166. /* compatibility aliases */
  167.     {"rp",            no_argument,        NULL,  1},
  168.     {"so",            no_argument,        NULL,  3},
  169.     {NULL,            0,                    NULL,  0}
  170. };
  171.  
  172. /* current module */
  173. MODULE *mf=NULL;
  174.  
  175. /* module parameters */
  176. BOOL cfg_extspd=1;    /* Extended Speed enable */
  177. BOOL cfg_panning=1;    /* DMP panning enable (8xx effects) */
  178. BOOL cfg_wrap=0;    /* auto song-wrapping disable */
  179. BOOL cfg_loop=1;    /* allow module to loop */
  180. BOOL cfg_fade=0;    /* allow volume fade during last pattern */
  181. BOOL cfg_curious=0;    /* look for extra patterns */
  182.  
  183. /* set if quiet mode is enabled */
  184. int quiet=0;
  185. int semiquiet=0;
  186.  
  187. int player_on=0;
  188.  
  189. /* playlist handling */
  190. int dorandom=0,playonce=0;
  191. BOOL next;
  192.  
  193. #if defined(__EMX__)||defined(__OS2__)
  194. #ifdef __EMX__
  195. int kbhit(void)
  196. {
  197.     KBDKEYINFO k;
  198.      
  199.     if(KbdPeek(&k,0)) return 0;
  200.     else return (k.fbStatus&KBDTRF_FINAL_CHAR_IN);
  201. }
  202. #endif
  203.  
  204. int mikmod_getch(void)
  205. {
  206.     int c=getch();
  207.         
  208.     if((!c)||(c==0xe0)) c=0x100|getch();
  209.     return c;
  210. }
  211.  
  212. #define KEY_UP (0x100|72)
  213. #define KEY_DOWN (0x100|80)
  214. #define KEY_LEFT (0x100|75)
  215. #define KEY_RIGHT (0x100|77)
  216. #define KEY_NPAGE (0x100|81)
  217. #define KEY_PPAGE (0x100|73)
  218. #define KEY_F(x) (0x100|(58+(x)))
  219. #define KEY_SF(x) (0x100|(83+(x)))
  220. #define getch mikmod_getch
  221.  
  222. #define RETSIGTYPE void
  223. #endif
  224.  
  225. /* signal handlers */
  226. RETSIGTYPE GotoNext(int signum)
  227. {
  228.     next=1;
  229.  
  230.     signal(SIGUSR1, GotoNext);
  231. }
  232.  
  233. RETSIGTYPE GotoPrev(int signum)
  234. {
  235.     PL_GetPrev(&playlist,NULL,NULL);
  236.     PL_GetPrev(&playlist,NULL,NULL);
  237.     next=1; 
  238.  
  239.     signal(SIGUSR2, GotoPrev);
  240. }
  241.  
  242. RETSIGTYPE ExitGracefully(int signum)
  243. {
  244.     if (player_on) MikMod_Exit();
  245.     if (curses_on) exit_display();
  246.  
  247.     if(!quiet)
  248.         fputs((signum==SIGTERM)?"Halted by SIGTERM\n":"Halted by SIGINT\n",stderr);
  249.  
  250.     signal(SIGINT,SIG_DFL);
  251.     signal(SIGTERM,SIG_DFL);
  252.     exit(0);
  253. }
  254.  
  255. int main(int argc,char *argv[])
  256. {
  257.     int t,quit=0,finished=0;
  258.     char filename[PATH_MAX];
  259.     char archive[PATH_MAX];
  260.     char *playfile;
  261.     int cfg_maxchn=128,c;
  262.     int tolerant=0;
  263.     int uservolume=128;
  264.     long engineversion=MikMod_GetVersion();
  265.  
  266. #ifdef __EMX__
  267.     _wildcard(&argc,&argv);
  268. #endif
  269.  
  270.     if (engineversion<LIBMIKMOD_VERSION) {
  271.         fprintf(stderr,"The current engine version (%ld.%ld.%ld) is too old.\n"
  272.                        "This programs requires at least version %ld.%ld.%ld\n",
  273.             (engineversion>>16)&255,(engineversion>>8)&255,(engineversion)&255,
  274.             LIBMIKMOD_VERSION_MAJOR,LIBMIKMOD_VERSION_MINOR,LIBMIKMOD_REVISION);
  275.         exit(2);
  276.     }
  277.  
  278.     /* Initialize soundcard parameters.. you _have_ to do this before calling
  279.        MikMod_Init(), and it's illegal to change them after you've called
  280.        MikMod_Init()
  281.     */
  282.     md_mixfreq      = 44100;    /* standard mixing freq */
  283.     md_device       = 0;        /* standard device: autodetect */
  284.     md_pansep       = 128;        /* panning separation (0=mono 128=full stereo)*/
  285.     md_reverb       = 0;        /* Reverb (max 15) */
  286.     /* default mixing mode */
  287.     md_mode            = DMODE_16BITS | DMODE_STEREO | DMODE_SOFT_MUSIC;
  288.  
  289.     /* Register the loaders we want to use:  */
  290.     MikMod_RegisterAllLoaders();
  291.  
  292.     /* Register the drivers we want to use: */
  293.     MikMod_RegisterAllDrivers();
  294.  
  295.     PL_InitList(&playlist);
  296.  
  297.     /* Getopt comes back ! */
  298.     opterr=0;
  299.     while((t=getopt_long_only(argc,argv,"8Fciklmnqrtxd:e:f:p::v:",
  300. #if defined(__OS2__)||defined(__EMX__)
  301.            options,NULL))>=0) {
  302. #else
  303.            options,NULL))!=ERR) {
  304. #endif
  305.         switch(t) {
  306.             case   1: /* --random */
  307.                 dorandom=1;
  308.                 break;
  309.             case   2: /* --playlist xxx */
  310.                 PL_Load(&playlist,optarg);
  311.                 break;
  312.             case   3: /* --terse */
  313.                 semiquiet=1;
  314.                 break;
  315.             case   4: /* --surround */
  316.                 md_mode|=DMODE_SURROUND;
  317.                 break;
  318.             case '8': /* -8 --eightbits */
  319.                 md_mode&=~DMODE_16BITS;
  320.                 break;
  321.             case 'F': /* -F --fadeout */
  322.                 cfg_fade=1;
  323.                 break;
  324.             case 'c': /* -c --curious */
  325.                 cfg_curious=1;
  326.                 break;
  327.             case 'i': /* -i --interpolate */
  328. #ifndef VIRTCH2
  329.                 md_mode|=DMODE_INTERP;
  330. #endif
  331.                 break;
  332.             case 'k': /* -k --once */
  333.                 playonce=1;
  334.                 break;
  335.             case 'm': /* -m --mono */
  336.                 md_mode&=~DMODE_STEREO;
  337.                 break;
  338.             case 'n': /* -n --noloops */
  339.                 cfg_loop=0;
  340.                 break;
  341.             case 'q': /* -q --quiet */
  342.                 quiet=1;
  343.                 break;
  344.             case 'r': /* -r --repeat */
  345.                 cfg_wrap=1;
  346.                 break;
  347.             case 's': /* -s --renice */
  348. #ifdef CPUTIME_SNAGGER
  349. #if defined(__FreeBSD__)||defined(__NetBSD__)||defined(__OpenBSD__)
  350.                 if(setpriority(PRIO_PROCESS,0,-20)==-1)
  351.                     perror("renice to -20");
  352. #endif
  353. #if defined(__linux)
  354.                 if (nice(-20)==-1)
  355.                     perror("renice to -20");
  356. #endif
  357. #if defined(__OS2__)||defined(__EMX__)
  358.                 DosSetPriority(PRTYS_PROCESSTREE,PRTYC_NOCHANGE,20,0);
  359. #endif
  360. #endif
  361.                 break;
  362.             case 'S': /* -S --realtime */
  363. #ifdef CPUTIME_SNAGGER
  364. #ifdef __FreeBSD__
  365.                 rtp.type=RTP_PRIO_REALTIME;
  366.                 rtp.prio=0;
  367.                 if (rtprio(RTP_SET,0,&rtp)==-1)
  368.                     perror("realtime priority");
  369. #endif
  370. #ifdef __linux
  371.             {
  372.                 struct sched_param sp;
  373.  
  374.                 memset(&sp,0,sizeof(struct sched_param));
  375.                 sp.sched_priority=1;
  376.                 if (sched_setscheduler(0,SCHED_RR,&sp)==-1)
  377.                     perror("realtime priority");
  378.             }
  379. #endif
  380. #if defined(__OS2__)||defined(__EMX__)
  381.                 DosSetPriority(PRTYS_PROCESSTREE,PRTYC_TIMECRITICAL,20,0);
  382. #endif
  383. #endif
  384.                 break;
  385.             case 't': /* -t --tolerant */
  386.                 tolerant=1;
  387.                 break;
  388.             case 'x': /* -x --protracker */
  389.                 cfg_extspd=0;
  390.                 break;
  391.             case 'd': /* -d --driver */
  392.                 md_device=atoi(optarg);
  393.                 break;
  394.             case 'e': /* -e --reverb */
  395.                 md_reverb=atoi(optarg);
  396.                 break;
  397.             case 'f': /* -f --frequency */
  398.                 md_mixfreq=atol(optarg);
  399.                 break;
  400.             case 'v': /* -v --volume */
  401.                 md_volume=(atoi(optarg)*128)/100;
  402.                 break;
  403.             case 'p': /* -p --panning */
  404.                 cfg_panning=optarg?atoi(optarg):0;
  405.                 break;
  406.             case 'l': /* -l --information */
  407.                 puts(mikcopyr);
  408.                 printf("\nAvailable drivers are :\n%s\n\nAvailable module loaders are :\n%s\n",
  409.                        MikMod_InfoDriver(),MikMod_InfoLoader());
  410.                 exit(0);
  411.             case 'h': /* -h --help */
  412.                 puts(mikcopyr);
  413.                 puts(helptext);
  414.                 exit(0);
  415.             case 'V': /* --version */
  416.                 puts(mikcopyr);
  417.                 printf("Sound engine version %ld.%ld.%ld\n",
  418.                        (engineversion>>16)&255,(engineversion>>8)&255,
  419.                        (engineversion)&255);
  420.                 exit(0);
  421.             default:
  422.                 /* ignore errors */
  423.                 break;
  424.         }
  425.  
  426.     }
  427.  
  428.     /* if neither a module nor a playlist was specified, display help and exit */
  429.     if((optind>=argc)&&(!playlist.numused)) {
  430.         puts(mikcopyr);
  431.         puts(helptext);
  432.         exit(0);
  433.     }
  434.  
  435.     /* Add remaining parameters to the playlist */
  436.     for(t=optind;t<argc;t++)
  437.         MA_FindFiles(&playlist,argv[t]);
  438.     if (dorandom)
  439.         PL_Randomize(&playlist);
  440.  
  441.     if (!quiet)
  442.         puts(mikbanner);
  443.  
  444.     if (!playlist.numused) {
  445.         puts("No file in playlist...");
  446.         exit(0);
  447.     }
  448.  
  449.     /*  initialize volume and tempo multipliers */
  450.     if (MikMod_Init()) {
  451.         fprintf(stderr,"MikMod initialisation error : %s\n",MikMod_strerror(MikMod_errno));
  452.         exit(1);
  453.     }
  454.     player_on=1;
  455.  
  456.     /*  initialize interface */
  457.     init_display();
  458.  
  459.     signal(SIGTERM,ExitGracefully);
  460.     signal(SIGINT,ExitGracefully);
  461.  
  462.     while(!quit) {
  463.         memset(filename,0,sizeof(filename));    
  464.         memset(archive,0,sizeof(archive));    
  465.         if((PL_GetNext(&playlist,filename,archive))) {
  466.             finished=1;
  467.             break;
  468.         }
  469.         if(!filename[0]) {
  470.             quit=1;
  471.             break;
  472.         }
  473.  
  474.         /* load the module */
  475.         playfile=MA_dearchive(archive,filename);
  476.         display_loadbanner();
  477.  
  478.         mf=Player_Load(playfile,cfg_maxchn,cfg_curious);
  479.         if(archive[0]) unlink(playfile);
  480.         if(!mf) {
  481.             /* didn't work -> exit with errormsg. */
  482.             if(!tolerant) {
  483.                 exit_display();
  484.                 if(archive[0])
  485.                     fprintf(stderr,"MikMod error : can't load %s from archive "
  486.                         "%s\n(reason: %s)\n",
  487.                         filename,archive,MikMod_strerror(MikMod_errno));
  488.                 else
  489.                     fprintf(stderr,"MikMod error : can't load %s\n"
  490.                         "(reason: %s)\n",
  491.                         playfile,MikMod_strerror(MikMod_errno));
  492.                 free(playfile);
  493.                 MikMod_Exit();
  494.                 player_on=0;
  495.                 exit(1);
  496.             } else {
  497.                 free(playfile);
  498.                 PL_DelCurrent(&playlist);
  499.                 continue;
  500.             }
  501.         }
  502.         free(playfile);
  503.  
  504.         mf->extspd  = cfg_extspd;
  505.         mf->panflag = cfg_panning;
  506.         mf->wrap    = cfg_wrap;
  507.         mf->loop    = cfg_loop;
  508.         mf->fadeout = cfg_fade;
  509.  
  510.         Player_Start(mf);
  511.         if (mf->volume>uservolume) Player_SetVolume(uservolume);
  512.  
  513.         firstinst=0; 
  514.         display_all();
  515.  
  516.         next=0;
  517.         signal(SIGUSR1, GotoNext);
  518.         signal(SIGUSR2, GotoPrev);
  519.  
  520.         /* if we have a quit signal, exit loop */
  521.         while(Player_Active() && !quit && !next) {
  522.             MikMod_Update();
  523. #if defined(__OS2__)||defined(__EMX__)
  524.             DosSleep(10);
  525. #else
  526.             usleep(10000);
  527. #endif
  528.  
  529.             /* update the status display... */
  530.             if(!Player_Paused())
  531.                 display_status();
  532.  
  533. #if defined(__OS2__)||defined(__EMX__)
  534.             if(!quiet && (c=(kbhit()?getch():0))!=EOF) {
  535. #else
  536.             if(!quiet && (c=getch())!=ERR) {
  537. #endif
  538.                 /* toggle pause */
  539.                 if (c==' ') {
  540.                     if(Player_Paused())
  541.                         display_all();
  542.                     else
  543.                         display_pausebanner();
  544.                     Player_TogglePause();
  545.                 }
  546.                 if (isalpha(c)) c=toupper(c);
  547.                 /* always enabled commands */
  548.                 switch(c) {
  549.                     case 'N':
  550.                         next=1;
  551.                         break;
  552.                     case 'P':
  553.                         PL_GetPrev(&playlist,filename,archive);
  554.                         PL_GetPrev(&playlist,filename,archive);
  555.                         next=1;
  556.                         break;
  557.                     case 'Q':
  558.                         quit=1;
  559.                         break;
  560.                     case 12: /* ^L */
  561. #if !defined(__OS2__)&&!defined(__EMX__)
  562.                     case KEY_CLEAR:
  563. #endif
  564.                         display_all();
  565.                         break;
  566.                 }
  567.                 /* commands that only work when module is not paused */
  568.                 if (!Player_Paused())
  569.                     switch(c) {
  570.                         case '+': 
  571.                         case KEY_RIGHT:
  572.                             Player_NextPosition();
  573.                             break;
  574.                         case '-': 
  575.                         case KEY_LEFT:
  576.                             Player_PrevPosition();
  577.                             break;
  578.                         case '(':
  579.                             Player_SetSpeed(mf->sngspd-1);
  580.                             break;
  581.                         case ')':
  582.                             Player_SetSpeed(mf->sngspd+1);
  583.                             break;
  584.                         case '{':
  585.                             Player_SetTempo(mf->bpm-1);
  586.                             break;
  587.                         case '}':
  588.                             Player_SetTempo(mf->bpm+1);
  589.                             break;
  590. #ifndef VIRTCH2
  591.                         case ';':
  592.                         case ':':
  593.                             md_mode^=DMODE_INTERP;
  594.                             display_driver();
  595.                             break;
  596. #endif
  597.                         case 'S':
  598.                             md_mode^=DMODE_SURROUND;
  599.                             display_driver();
  600.                             break;
  601.                         case KEY_DOWN:
  602.                             firstinst++;
  603.                             display_information();
  604.                             break;
  605.                         case KEY_UP:
  606.                             if (firstinst) {
  607.                                 firstinst--;
  608.                                 display_information();
  609.                             }
  610.                             break;
  611.                         case KEY_NPAGE:
  612.                             firstinst+=(winy-6);
  613.                             display_information();
  614.                             break;
  615.                         case KEY_PPAGE:
  616.                             firstinst-=(winy-6);
  617.                             display_information();
  618.                             break;
  619.                         case KEY_F(1):
  620.                         case KEY_F(2):
  621.                         case KEY_F(3):
  622.                         case KEY_F(4):
  623.                         case KEY_F(5):
  624.                         case KEY_F(6):
  625.                         case KEY_F(7):
  626.                         case KEY_F(8):
  627.                         case KEY_F(9):
  628.                         case KEY_F(10):
  629.                             Player_SetVolume(uservolume=((((c-KEY_F(0))<<7)+5)/10));
  630.                             break;
  631.                         case '<':
  632.                             if(mf->volume)
  633.                                 Player_SetVolume(uservolume=mf->volume-1);
  634.                             break;
  635.                         case '>':
  636.                             if(mf->volume<128)
  637.                                 Player_SetVolume(uservolume=mf->volume+1);
  638.                             break;
  639.                         case 'W':
  640.                             PL_Save(&playlist, "./mikmodplaylist");
  641.                             break;
  642.                         case 'I':
  643.                             firstinst=0;
  644.                             dispsamp=(dispsamp&1)^1;
  645.                             display_information();
  646.                             break;
  647.                         case 'M':
  648. #if defined(__OS2__)||defined(__EMX__)
  649.                         case KEY_SF(9): /* shift-F9 */
  650. #else
  651.                         case KEY_F(19): /* shift-F9 */
  652. #endif
  653.                             if(mf->comment) {
  654.                                 firstinst=0;
  655.                                 if(dispsamp&4)
  656.                                     dispsamp=(dispsamp&3)|2;
  657.                                 else
  658.                                     dispsamp=(dispsamp&3)^2;
  659.                                 display_information();
  660.                             }
  661.                             break;
  662.                         case 'H':
  663.                             if (dispsamp&4)
  664.                                 dispsamp=(dispsamp&~4)|8;
  665.                             else
  666.                                 dispsamp=(dispsamp&~8)|4;
  667.                             display_information();
  668.                             break;
  669.                     }
  670. #if !defined(__OS2__)&&!defined(__EMX__)
  671.                 if(!quiet) flushinp();
  672. #endif
  673.             }
  674.         }
  675.         Player_Stop();        /* stop playing */
  676.         Player_Free(mf);    /* and free the module */
  677.         if (playonce) PL_DelCurrent(&playlist);
  678.     }
  679.  
  680.     MikMod_Exit();
  681.     player_on=0;
  682.     exit_display();
  683.     if ((!quit)&&(!quiet)) {
  684.         if(!finished) {
  685.             fprintf(stderr,"MikMod error : %s\n",MikMod_strerror(MikMod_errno));
  686.             exit(1);
  687.         } else
  688.             puts("Finished playlist...");
  689.     }
  690.     exit(0);
  691. }
  692.