home *** CD-ROM | disk | FTP | other *** search
- /* MikMod example player
- (c) 1998 Miodrag Vallat and others - see file AUTHORS for complete list
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /*==============================================================================
-
- $Id: mikmod.c,v 1.42 1998/12/07 06:01:25 miod Exp $
-
- Module player example of MikMod
-
- ==============================================================================*/
-
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
-
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include <ctype.h>
- #ifdef HAVE_GETOPT_LONG_ONLY
- #include <getopt.h>
- #else
- #include "../extra/getopt.h"
- #endif
- #ifdef HAVE_LIMITS_H
- #include <limits.h>
- #endif
- #ifdef __EMX__
- #define PATH_MAX _POSIX_PATH_MAX
- #endif
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #ifdef NEED_USLEEP
- void usleep(unsigned long);
- #endif
- #if defined(__OS2__)||defined(__EMX__)
- #define INCL_DOS
- #define INCL_KBD
- #include <os2.h>
- #endif
-
- #if !defined(__OS2__)&&!defined(__EMX__)
- #ifdef HAVE_NCURSES_H
- #include <ncurses.h>
- #else
- #include <curses.h>
- #endif
- #else
- #include <conio.h>
- #endif
-
- #include <mikmod.h>
-
- #include "player.h"
-
- #ifdef CPUTIME_SNAGGER
- #if defined(__FreeBSD__)||defined(__NetBSD__)||defined(__OpenBSD__)
- #ifdef HAVE_SYS_TIME_H
- #include <sys/time.h>
- #endif
- #include <sys/resource.h>
- #include <sys/types.h>
- #ifdef __FreeBSD__
- #include <sys/rtprio.h>
- #endif
- #endif
- #if defined(__linux)
- #ifdef BROKEN_SCHED
- #define _P __P
- #endif
- #include <sched.h>
- #endif
- #if defined(__OS2__)||defined(__EMX__)
- #define INCL_DOSPROCESS
- #include <os2.h>
- #endif
- #endif
-
- PLAYLIST playlist;
- #ifdef CPUTIME_SNAGGER
- #ifdef __FreeBSD__
- struct rtprio rtp;
- #endif
- #endif
-
- char helptext[]=
- "\nAvailable switches:\n"
- "-c[urious] Look for hidden patterns in module.\n"
- "-d[river] n Use nth driver for output. Default is 0 (autodetect).\n"
- "-8, -ei[ghtbits] Force 8 bit output.\n"
- "-F, -fa[deout] Force volume fade at the end of the module.\n"
- "-f[requency] nnnnn Sets mixing frequency. Default is 44100.\n"
- #ifndef VIRTCH2
- "-i[nterpolate] Use interpolate mixing.\n"
- #endif
- "-k, -o[nce] Play files only once.\n"
- "-m[ono] Force mono output.\n"
- "-n[oloops] Disables in-module loops.\n"
- "-p, -pa[nning] nn Sets default panning (0=left,255=right,128=center).\n"
- "-pl[aylist] file Use playlist.\n"
- "-x, -pr[otracker] Disable extended protracker effects.\n"
- "-q[uiet] Quiet mode, no interface, displays only errors.\n"
- "-ra[ndom] Random file play.\n"
- #ifdef CPUTIME_SNAGGER
- "-s, -ren[ice] Renice to -20 (more scheduling priority).\n"
- #ifndef __OpenBSD__
- "-S, -rea[ltime] Get realtime priority (will hog CPU power).\n"
- #endif
- #endif
- "-r[epeat] Repeat module after it's finished.\n"
- "-e, -rev[erb] nn Set reverb amount. Default is 0 (none), max is 15.\n"
- "-su[rround] Use surround mixing.\n"
- "-te[rse] Terse output : status line only.\n"
- "-t[olerant] Tolerant mode : don't halt on file access errors.\n"
- "-v[olume] nn Sets volume from 0% (silence) to 100%. Default is 100%.\n"
- "\n"
- "-l, -inf[ormation] List all available drivers and module loaders.\n"
- "\n"
- "-ve[rsion] Display MikMod version.\n"
- "-h[elp] Display this help screen.\n";
-
- /* Long options definition */
- struct option options[]={
- {"curious", no_argument, NULL,'c'},
- {"driver", required_argument, NULL,'d'},
- {"eightbits", no_argument, NULL,'8'},
- {"fadeout", no_argument, NULL,'F'},
- {"frequency", required_argument, NULL,'f'},
- {"interpolate", no_argument, NULL,'i'},
- {"mono", no_argument, NULL,'m'},
- {"noloops", no_argument, NULL,'n'},
- {"once", no_argument, NULL,'k'},
- {"panning", optional_argument, NULL,'p'},
- {"playlist", required_argument, NULL, 2}, /* pl */
- {"protracker", no_argument, NULL,'x'},
- {"quiet", no_argument, NULL,'q'},
- {"random", no_argument, NULL, 1}, /* rp */
- {"realtime", no_argument, NULL,'S'},
- {"renice", no_argument, NULL,'s'},
- {"repeat", no_argument, NULL,'r'},
- {"reverb", required_argument, NULL,'e'},
- {"surround", no_argument, NULL, 4},
- {"terse", no_argument, NULL, 3}, /* so */
- {"tolerant", no_argument, NULL,'t'},
- {"volume", required_argument, NULL,'v'},
- {"information", no_argument, NULL,'l'},
- {"version", no_argument, NULL,'V'},
- {"help", no_argument, NULL,'h'},
- /* compatibility aliases */
- {"rp", no_argument, NULL, 1},
- {"so", no_argument, NULL, 3},
- {NULL, 0, NULL, 0}
- };
-
- /* current module */
- MODULE *mf=NULL;
-
- /* module parameters */
- BOOL cfg_extspd=1; /* Extended Speed enable */
- BOOL cfg_panning=1; /* DMP panning enable (8xx effects) */
- BOOL cfg_wrap=0; /* auto song-wrapping disable */
- BOOL cfg_loop=1; /* allow module to loop */
- BOOL cfg_fade=0; /* allow volume fade during last pattern */
- BOOL cfg_curious=0; /* look for extra patterns */
-
- /* set if quiet mode is enabled */
- int quiet=0;
- int semiquiet=0;
-
- int player_on=0;
-
- /* playlist handling */
- int dorandom=0,playonce=0;
- BOOL next;
-
- #if defined(__EMX__)||defined(__OS2__)
- #ifdef __EMX__
- int kbhit(void)
- {
- KBDKEYINFO k;
-
- if(KbdPeek(&k,0)) return 0;
- else return (k.fbStatus&KBDTRF_FINAL_CHAR_IN);
- }
- #endif
-
- int mikmod_getch(void)
- {
- int c=getch();
-
- if((!c)||(c==0xe0)) c=0x100|getch();
- return c;
- }
-
- #define KEY_UP (0x100|72)
- #define KEY_DOWN (0x100|80)
- #define KEY_LEFT (0x100|75)
- #define KEY_RIGHT (0x100|77)
- #define KEY_NPAGE (0x100|81)
- #define KEY_PPAGE (0x100|73)
- #define KEY_F(x) (0x100|(58+(x)))
- #define KEY_SF(x) (0x100|(83+(x)))
- #define getch mikmod_getch
-
- #define RETSIGTYPE void
- #endif
-
- /* signal handlers */
- RETSIGTYPE GotoNext(int signum)
- {
- next=1;
-
- signal(SIGUSR1, GotoNext);
- }
-
- RETSIGTYPE GotoPrev(int signum)
- {
- PL_GetPrev(&playlist,NULL,NULL);
- PL_GetPrev(&playlist,NULL,NULL);
- next=1;
-
- signal(SIGUSR2, GotoPrev);
- }
-
- RETSIGTYPE ExitGracefully(int signum)
- {
- if (player_on) MikMod_Exit();
- if (curses_on) exit_display();
-
- if(!quiet)
- fputs((signum==SIGTERM)?"Halted by SIGTERM\n":"Halted by SIGINT\n",stderr);
-
- signal(SIGINT,SIG_DFL);
- signal(SIGTERM,SIG_DFL);
- exit(0);
- }
-
- int main(int argc,char *argv[])
- {
- int t,quit=0,finished=0;
- char filename[PATH_MAX];
- char archive[PATH_MAX];
- char *playfile;
- int cfg_maxchn=128,c;
- int tolerant=0;
- int uservolume=128;
- long engineversion=MikMod_GetVersion();
-
- #ifdef __EMX__
- _wildcard(&argc,&argv);
- #endif
-
- if (engineversion<LIBMIKMOD_VERSION) {
- fprintf(stderr,"The current engine version (%ld.%ld.%ld) is too old.\n"
- "This programs requires at least version %ld.%ld.%ld\n",
- (engineversion>>16)&255,(engineversion>>8)&255,(engineversion)&255,
- LIBMIKMOD_VERSION_MAJOR,LIBMIKMOD_VERSION_MINOR,LIBMIKMOD_REVISION);
- exit(2);
- }
-
- /* Initialize soundcard parameters.. you _have_ to do this before calling
- MikMod_Init(), and it's illegal to change them after you've called
- MikMod_Init()
- */
- md_mixfreq = 44100; /* standard mixing freq */
- md_device = 0; /* standard device: autodetect */
- md_pansep = 128; /* panning separation (0=mono 128=full stereo)*/
- md_reverb = 0; /* Reverb (max 15) */
- /* default mixing mode */
- md_mode = DMODE_16BITS | DMODE_STEREO | DMODE_SOFT_MUSIC;
-
- /* Register the loaders we want to use: */
- MikMod_RegisterAllLoaders();
-
- /* Register the drivers we want to use: */
- MikMod_RegisterAllDrivers();
-
- PL_InitList(&playlist);
-
- /* Getopt comes back ! */
- opterr=0;
- while((t=getopt_long_only(argc,argv,"8Fciklmnqrtxd:e:f:p::v:",
- #if defined(__OS2__)||defined(__EMX__)
- options,NULL))>=0) {
- #else
- options,NULL))!=ERR) {
- #endif
- switch(t) {
- case 1: /* --random */
- dorandom=1;
- break;
- case 2: /* --playlist xxx */
- PL_Load(&playlist,optarg);
- break;
- case 3: /* --terse */
- semiquiet=1;
- break;
- case 4: /* --surround */
- md_mode|=DMODE_SURROUND;
- break;
- case '8': /* -8 --eightbits */
- md_mode&=~DMODE_16BITS;
- break;
- case 'F': /* -F --fadeout */
- cfg_fade=1;
- break;
- case 'c': /* -c --curious */
- cfg_curious=1;
- break;
- case 'i': /* -i --interpolate */
- #ifndef VIRTCH2
- md_mode|=DMODE_INTERP;
- #endif
- break;
- case 'k': /* -k --once */
- playonce=1;
- break;
- case 'm': /* -m --mono */
- md_mode&=~DMODE_STEREO;
- break;
- case 'n': /* -n --noloops */
- cfg_loop=0;
- break;
- case 'q': /* -q --quiet */
- quiet=1;
- break;
- case 'r': /* -r --repeat */
- cfg_wrap=1;
- break;
- case 's': /* -s --renice */
- #ifdef CPUTIME_SNAGGER
- #if defined(__FreeBSD__)||defined(__NetBSD__)||defined(__OpenBSD__)
- if(setpriority(PRIO_PROCESS,0,-20)==-1)
- perror("renice to -20");
- #endif
- #if defined(__linux)
- if (nice(-20)==-1)
- perror("renice to -20");
- #endif
- #if defined(__OS2__)||defined(__EMX__)
- DosSetPriority(PRTYS_PROCESSTREE,PRTYC_NOCHANGE,20,0);
- #endif
- #endif
- break;
- case 'S': /* -S --realtime */
- #ifdef CPUTIME_SNAGGER
- #ifdef __FreeBSD__
- rtp.type=RTP_PRIO_REALTIME;
- rtp.prio=0;
- if (rtprio(RTP_SET,0,&rtp)==-1)
- perror("realtime priority");
- #endif
- #ifdef __linux
- {
- struct sched_param sp;
-
- memset(&sp,0,sizeof(struct sched_param));
- sp.sched_priority=1;
- if (sched_setscheduler(0,SCHED_RR,&sp)==-1)
- perror("realtime priority");
- }
- #endif
- #if defined(__OS2__)||defined(__EMX__)
- DosSetPriority(PRTYS_PROCESSTREE,PRTYC_TIMECRITICAL,20,0);
- #endif
- #endif
- break;
- case 't': /* -t --tolerant */
- tolerant=1;
- break;
- case 'x': /* -x --protracker */
- cfg_extspd=0;
- break;
- case 'd': /* -d --driver */
- md_device=atoi(optarg);
- break;
- case 'e': /* -e --reverb */
- md_reverb=atoi(optarg);
- break;
- case 'f': /* -f --frequency */
- md_mixfreq=atol(optarg);
- break;
- case 'v': /* -v --volume */
- md_volume=(atoi(optarg)*128)/100;
- break;
- case 'p': /* -p --panning */
- cfg_panning=optarg?atoi(optarg):0;
- break;
- case 'l': /* -l --information */
- puts(mikcopyr);
- printf("\nAvailable drivers are :\n%s\n\nAvailable module loaders are :\n%s\n",
- MikMod_InfoDriver(),MikMod_InfoLoader());
- exit(0);
- case 'h': /* -h --help */
- puts(mikcopyr);
- puts(helptext);
- exit(0);
- case 'V': /* --version */
- puts(mikcopyr);
- printf("Sound engine version %ld.%ld.%ld\n",
- (engineversion>>16)&255,(engineversion>>8)&255,
- (engineversion)&255);
- exit(0);
- default:
- /* ignore errors */
- break;
- }
-
- }
-
- /* if neither a module nor a playlist was specified, display help and exit */
- if((optind>=argc)&&(!playlist.numused)) {
- puts(mikcopyr);
- puts(helptext);
- exit(0);
- }
-
- /* Add remaining parameters to the playlist */
- for(t=optind;t<argc;t++)
- MA_FindFiles(&playlist,argv[t]);
- if (dorandom)
- PL_Randomize(&playlist);
-
- if (!quiet)
- puts(mikbanner);
-
- if (!playlist.numused) {
- puts("No file in playlist...");
- exit(0);
- }
-
- /* initialize volume and tempo multipliers */
- if (MikMod_Init()) {
- fprintf(stderr,"MikMod initialisation error : %s\n",MikMod_strerror(MikMod_errno));
- exit(1);
- }
- player_on=1;
-
- /* initialize interface */
- init_display();
-
- signal(SIGTERM,ExitGracefully);
- signal(SIGINT,ExitGracefully);
-
- while(!quit) {
- memset(filename,0,sizeof(filename));
- memset(archive,0,sizeof(archive));
- if((PL_GetNext(&playlist,filename,archive))) {
- finished=1;
- break;
- }
- if(!filename[0]) {
- quit=1;
- break;
- }
-
- /* load the module */
- playfile=MA_dearchive(archive,filename);
- display_loadbanner();
-
- mf=Player_Load(playfile,cfg_maxchn,cfg_curious);
- if(archive[0]) unlink(playfile);
- if(!mf) {
- /* didn't work -> exit with errormsg. */
- if(!tolerant) {
- exit_display();
- if(archive[0])
- fprintf(stderr,"MikMod error : can't load %s from archive "
- "%s\n(reason: %s)\n",
- filename,archive,MikMod_strerror(MikMod_errno));
- else
- fprintf(stderr,"MikMod error : can't load %s\n"
- "(reason: %s)\n",
- playfile,MikMod_strerror(MikMod_errno));
- free(playfile);
- MikMod_Exit();
- player_on=0;
- exit(1);
- } else {
- free(playfile);
- PL_DelCurrent(&playlist);
- continue;
- }
- }
- free(playfile);
-
- mf->extspd = cfg_extspd;
- mf->panflag = cfg_panning;
- mf->wrap = cfg_wrap;
- mf->loop = cfg_loop;
- mf->fadeout = cfg_fade;
-
- Player_Start(mf);
- if (mf->volume>uservolume) Player_SetVolume(uservolume);
-
- firstinst=0;
- display_all();
-
- next=0;
- signal(SIGUSR1, GotoNext);
- signal(SIGUSR2, GotoPrev);
-
- /* if we have a quit signal, exit loop */
- while(Player_Active() && !quit && !next) {
- MikMod_Update();
- #if defined(__OS2__)||defined(__EMX__)
- DosSleep(10);
- #else
- usleep(10000);
- #endif
-
- /* update the status display... */
- if(!Player_Paused())
- display_status();
-
- #if defined(__OS2__)||defined(__EMX__)
- if(!quiet && (c=(kbhit()?getch():0))!=EOF) {
- #else
- if(!quiet && (c=getch())!=ERR) {
- #endif
- /* toggle pause */
- if (c==' ') {
- if(Player_Paused())
- display_all();
- else
- display_pausebanner();
- Player_TogglePause();
- }
- if (isalpha(c)) c=toupper(c);
- /* always enabled commands */
- switch(c) {
- case 'N':
- next=1;
- break;
- case 'P':
- PL_GetPrev(&playlist,filename,archive);
- PL_GetPrev(&playlist,filename,archive);
- next=1;
- break;
- case 'Q':
- quit=1;
- break;
- case 12: /* ^L */
- #if !defined(__OS2__)&&!defined(__EMX__)
- case KEY_CLEAR:
- #endif
- display_all();
- break;
- }
- /* commands that only work when module is not paused */
- if (!Player_Paused())
- switch(c) {
- case '+':
- case KEY_RIGHT:
- Player_NextPosition();
- break;
- case '-':
- case KEY_LEFT:
- Player_PrevPosition();
- break;
- case '(':
- Player_SetSpeed(mf->sngspd-1);
- break;
- case ')':
- Player_SetSpeed(mf->sngspd+1);
- break;
- case '{':
- Player_SetTempo(mf->bpm-1);
- break;
- case '}':
- Player_SetTempo(mf->bpm+1);
- break;
- #ifndef VIRTCH2
- case ';':
- case ':':
- md_mode^=DMODE_INTERP;
- display_driver();
- break;
- #endif
- case 'S':
- md_mode^=DMODE_SURROUND;
- display_driver();
- break;
- case KEY_DOWN:
- firstinst++;
- display_information();
- break;
- case KEY_UP:
- if (firstinst) {
- firstinst--;
- display_information();
- }
- break;
- case KEY_NPAGE:
- firstinst+=(winy-6);
- display_information();
- break;
- case KEY_PPAGE:
- firstinst-=(winy-6);
- display_information();
- break;
- case KEY_F(1):
- case KEY_F(2):
- case KEY_F(3):
- case KEY_F(4):
- case KEY_F(5):
- case KEY_F(6):
- case KEY_F(7):
- case KEY_F(8):
- case KEY_F(9):
- case KEY_F(10):
- Player_SetVolume(uservolume=((((c-KEY_F(0))<<7)+5)/10));
- break;
- case '<':
- if(mf->volume)
- Player_SetVolume(uservolume=mf->volume-1);
- break;
- case '>':
- if(mf->volume<128)
- Player_SetVolume(uservolume=mf->volume+1);
- break;
- case 'W':
- PL_Save(&playlist, "./mikmodplaylist");
- break;
- case 'I':
- firstinst=0;
- dispsamp=(dispsamp&1)^1;
- display_information();
- break;
- case 'M':
- #if defined(__OS2__)||defined(__EMX__)
- case KEY_SF(9): /* shift-F9 */
- #else
- case KEY_F(19): /* shift-F9 */
- #endif
- if(mf->comment) {
- firstinst=0;
- if(dispsamp&4)
- dispsamp=(dispsamp&3)|2;
- else
- dispsamp=(dispsamp&3)^2;
- display_information();
- }
- break;
- case 'H':
- if (dispsamp&4)
- dispsamp=(dispsamp&~4)|8;
- else
- dispsamp=(dispsamp&~8)|4;
- display_information();
- break;
- }
- #if !defined(__OS2__)&&!defined(__EMX__)
- if(!quiet) flushinp();
- #endif
- }
- }
- Player_Stop(); /* stop playing */
- Player_Free(mf); /* and free the module */
- if (playonce) PL_DelCurrent(&playlist);
- }
-
- MikMod_Exit();
- player_on=0;
- exit_display();
- if ((!quit)&&(!quiet)) {
- if(!finished) {
- fprintf(stderr,"MikMod error : %s\n",MikMod_strerror(MikMod_errno));
- exit(1);
- } else
- puts("Finished playlist...");
- }
- exit(0);
- }
-