538 lines
12 KiB
C
538 lines
12 KiB
C
|
/*
|
||
|
Copyright (C) 1994-1995 Apogee Software, Ltd.
|
||
|
|
||
|
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
|
||
|
*/
|
||
|
/**********************************************************************
|
||
|
module: PM.C
|
||
|
|
||
|
author: James R. Dose
|
||
|
date: January 16, 1994
|
||
|
|
||
|
Simple music player.
|
||
|
|
||
|
(c) Copyright 1994 James R. Dose. All Rights Reserved.
|
||
|
**********************************************************************/
|
||
|
|
||
|
#include <conio.h>
|
||
|
#include <dos.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include "music.h"
|
||
|
|
||
|
|
||
|
/*---------------------------------------------------------------------
|
||
|
Function prototypes
|
||
|
---------------------------------------------------------------------*/
|
||
|
|
||
|
void LoadTimbres( char *timbrefile );
|
||
|
char *LoadMidi( char *filename );
|
||
|
char *GetUserText( const char *parameter );
|
||
|
int CheckUserParm( const char *parameter );
|
||
|
void DefaultExtension( char *path, char *extension );
|
||
|
void TurnOffTextCursor( void );
|
||
|
void TurnOnTextCursor( void );
|
||
|
|
||
|
#define TRUE ( 1 == 1 )
|
||
|
#define FALSE ( !TRUE )
|
||
|
|
||
|
#define NUMCARDS 10
|
||
|
|
||
|
char *SoundCardNames[] =
|
||
|
{
|
||
|
"General Midi", "Sound Canvas", "Awe 32", "WaveBlaster",
|
||
|
"SoundBlaster", "Pro AudioSpectrum", "Sound Man 16", "Adlib",
|
||
|
"Ensoniq SoundScape", "Gravis UltraSound"
|
||
|
};
|
||
|
|
||
|
int SoundCardNums[] =
|
||
|
{
|
||
|
GenMidi, SoundCanvas, Awe32, WaveBlaster,
|
||
|
SoundBlaster, ProAudioSpectrum, SoundMan16,
|
||
|
Adlib, SoundScape, UltraSound
|
||
|
};
|
||
|
|
||
|
/*---------------------------------------------------------------------
|
||
|
Function: main
|
||
|
|
||
|
Sets up sound cards, calls the demo, and then cleans up.
|
||
|
---------------------------------------------------------------------*/
|
||
|
|
||
|
void main
|
||
|
(
|
||
|
int argc,
|
||
|
char *argv[]
|
||
|
)
|
||
|
|
||
|
{
|
||
|
int card;
|
||
|
int address;
|
||
|
int status;
|
||
|
char *SongPtr = NULL;
|
||
|
char *ptr;
|
||
|
char filename[ 128 ];
|
||
|
char timbrefile[ 128 ];
|
||
|
int gotopos = 0;
|
||
|
int measure = 0;
|
||
|
int beat = 0;
|
||
|
int tick = 0;
|
||
|
int time = 0;
|
||
|
|
||
|
printf( "\nPM EMIDI Music Player Version 1.21 Copyright (c) 1996 by Jim Dose\n" );
|
||
|
|
||
|
if ( ( CheckUserParm( "?" ) ) || ( argc < 2 ) )
|
||
|
{
|
||
|
int index;
|
||
|
|
||
|
printf(
|
||
|
"Usage: PM [ midifile ] CARD=[ card number ] MPU=[ port address in hex ]\n"
|
||
|
" TIMBRE=[ timbre file ] TIME=[minutes:seconds:milliseconds]\n"
|
||
|
" POSITION=[measure:beat:tick]\n\n"
|
||
|
" card number = \n" );
|
||
|
for( index = 0; index < NUMCARDS; index++ )
|
||
|
{
|
||
|
printf( " %d : %s\n", index, SoundCardNames[ index ] );
|
||
|
}
|
||
|
|
||
|
printf( "\n" );
|
||
|
exit( 0 );
|
||
|
}
|
||
|
|
||
|
// Default is GenMidi
|
||
|
card = 0;
|
||
|
address = 0x330;
|
||
|
|
||
|
ptr = getenv( "PM" );
|
||
|
if ( ptr != NULL )
|
||
|
{
|
||
|
sscanf( ptr, "%d,%x", &card, &address );
|
||
|
}
|
||
|
|
||
|
ptr = GetUserText( "MPU" );
|
||
|
if ( ptr != NULL )
|
||
|
{
|
||
|
sscanf( ptr, "%x", &address );
|
||
|
}
|
||
|
|
||
|
ptr = GetUserText( "TIMBRE" );
|
||
|
if ( ptr != NULL )
|
||
|
{
|
||
|
sscanf( ptr, "%s", timbrefile );
|
||
|
LoadTimbres( timbrefile );
|
||
|
}
|
||
|
|
||
|
ptr = GetUserText( "POSITION" );
|
||
|
if ( ptr != NULL )
|
||
|
{
|
||
|
gotopos = 1;
|
||
|
sscanf( ptr, "%d:%d:%d", &measure, &beat, &tick );
|
||
|
}
|
||
|
|
||
|
ptr = GetUserText( "TIME" );
|
||
|
if ( ptr != NULL )
|
||
|
{
|
||
|
int minutes = 0;
|
||
|
int seconds = 0;
|
||
|
int milli = 0;
|
||
|
|
||
|
gotopos = 2;
|
||
|
sscanf( ptr, "%d:%d:%d", &minutes, &seconds, &milli );
|
||
|
time = minutes * ( 60 * 1000 ) + seconds * 1000 + milli;
|
||
|
}
|
||
|
|
||
|
ptr = GetUserText( "CARD" );
|
||
|
if ( ptr != NULL )
|
||
|
{
|
||
|
sscanf( ptr, "%d", &card );
|
||
|
}
|
||
|
|
||
|
if ( ( card < 0 ) || ( card >= NUMCARDS ) )
|
||
|
{
|
||
|
printf( "Value out of range for CARD: %d\n", card );
|
||
|
}
|
||
|
|
||
|
status = MUSIC_Init( SoundCardNums[ card ], address );
|
||
|
if ( status != MUSIC_Ok )
|
||
|
{
|
||
|
printf( "Error - %s\n", MUSIC_ErrorString( status ) );
|
||
|
exit( 1 );
|
||
|
}
|
||
|
|
||
|
strcpy( filename, argv[ 1 ] );
|
||
|
DefaultExtension( filename, ".mid" );
|
||
|
|
||
|
SongPtr = LoadMidi( filename );
|
||
|
|
||
|
MUSIC_SetVolume( 255 );
|
||
|
|
||
|
status = MUSIC_PlaySong( SongPtr, MUSIC_LoopSong );
|
||
|
if ( status != MUSIC_Ok )
|
||
|
{
|
||
|
printf( "Error - %s\n", MUSIC_ErrorString( status ) );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
char ch;
|
||
|
songposition pos;
|
||
|
|
||
|
if ( gotopos == 1 )
|
||
|
{
|
||
|
MUSIC_SetSongPosition( measure, beat, tick );
|
||
|
}
|
||
|
else if ( gotopos == 2 )
|
||
|
{
|
||
|
MUSIC_SetSongTime( time );
|
||
|
}
|
||
|
|
||
|
printf( "Playing file '%s'.\n\n", filename );
|
||
|
printf( "Press F to advance one measure.\n"
|
||
|
"Press R to rewind one measure.\n"
|
||
|
"Press G to go to the selected position.\n"
|
||
|
"Press ESCape to end.\n\n" );
|
||
|
|
||
|
MUSIC_GetSongLength( &pos );
|
||
|
printf( "Song length: time (m:s:ms) = %d:%d:%d, "
|
||
|
"(measure:beat:tick) = %d:%d:%d\n\n",
|
||
|
pos.milliseconds / (60*1000),
|
||
|
( pos.milliseconds / 1000 ) % 60,
|
||
|
pos.milliseconds % 1000,
|
||
|
pos.measure, pos.beat, pos.tick );
|
||
|
ch = 0;
|
||
|
|
||
|
TurnOffTextCursor();
|
||
|
while( ch != 27 )
|
||
|
{
|
||
|
MUSIC_GetSongPosition( &pos );
|
||
|
printf( "time (m:s:ms) = %d:%d:%d \t(measure:beat:tick) = %d:%d:%d \r",
|
||
|
pos.milliseconds / (60*1000),
|
||
|
( pos.milliseconds / 1000 ) % 60,
|
||
|
pos.milliseconds % 1000,
|
||
|
pos.measure, pos.beat, pos.tick );
|
||
|
fflush( stdout );
|
||
|
|
||
|
if ( kbhit() )
|
||
|
{
|
||
|
ch = getch();
|
||
|
|
||
|
if ( ( ch == 'G' ) || ( ch == 'g' ) )
|
||
|
{
|
||
|
if ( gotopos == 1 )
|
||
|
{
|
||
|
MUSIC_SetSongPosition( measure, beat, tick );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
MUSIC_SetSongTime( time );
|
||
|
}
|
||
|
|
||
|
ch = 0;
|
||
|
while( kbhit() )
|
||
|
{
|
||
|
getch();
|
||
|
}
|
||
|
}
|
||
|
if ( ( ch == 'F' ) || ( ch == 'f' ) )
|
||
|
{
|
||
|
MUSIC_SetSongPosition( pos.measure + 1, 1, 0 );
|
||
|
ch = 0;
|
||
|
while( kbhit() )
|
||
|
{
|
||
|
getch();
|
||
|
}
|
||
|
}
|
||
|
if ( ( ch == 'R' ) || ( ch == 'r' ) )
|
||
|
{
|
||
|
MUSIC_SetSongPosition( pos.measure - 1, 1, 0 );
|
||
|
ch = 0;
|
||
|
while( kbhit() )
|
||
|
{
|
||
|
getch();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TurnOnTextCursor();
|
||
|
MUSIC_StopSong();
|
||
|
}
|
||
|
|
||
|
free( SongPtr );
|
||
|
MUSIC_Shutdown();
|
||
|
printf( "\n" );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*---------------------------------------------------------------------
|
||
|
Function: LoadTimbres
|
||
|
|
||
|
Loads the instruments from disk
|
||
|
---------------------------------------------------------------------*/
|
||
|
|
||
|
void LoadTimbres
|
||
|
(
|
||
|
char *timbrefile
|
||
|
)
|
||
|
|
||
|
{
|
||
|
FILE *in;
|
||
|
long size;
|
||
|
char *TimbrePtr;
|
||
|
|
||
|
if ( ( in = fopen( timbrefile, "rb" ) ) == NULL )
|
||
|
{
|
||
|
printf( "Cannot open '%s' for read.\n", timbrefile );
|
||
|
exit( 1 );
|
||
|
}
|
||
|
|
||
|
fseek( in, 0, SEEK_END );
|
||
|
size = ftell( in );
|
||
|
fseek( in, 0, SEEK_SET );
|
||
|
|
||
|
TimbrePtr = ( char * )malloc( size );
|
||
|
if ( TimbrePtr == NULL )
|
||
|
{
|
||
|
printf( "Out of memory while reading '%s'.\n", timbrefile );
|
||
|
exit( 1 );
|
||
|
}
|
||
|
|
||
|
if ( fread( TimbrePtr, size, 1, in ) != 1 )
|
||
|
{
|
||
|
printf( "Unexpected end of file while reading '%s'.\n", timbrefile );
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
fclose( in );
|
||
|
|
||
|
MUSIC_RegisterTimbreBank( TimbrePtr );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*---------------------------------------------------------------------
|
||
|
Function: LoadMidi
|
||
|
|
||
|
Loads the midi file from disk.
|
||
|
---------------------------------------------------------------------*/
|
||
|
|
||
|
char *LoadMidi
|
||
|
(
|
||
|
char *filename
|
||
|
)
|
||
|
|
||
|
{
|
||
|
FILE *in;
|
||
|
long size;
|
||
|
char *MidiPtr;
|
||
|
|
||
|
if ( ( in = fopen( filename, "rb" ) ) == NULL )
|
||
|
{
|
||
|
printf( "Cannot open '%s' for read.\n", filename );
|
||
|
exit( 1 );
|
||
|
}
|
||
|
|
||
|
fseek( in, 0, SEEK_END );
|
||
|
size = ftell( in );
|
||
|
fseek( in, 0, SEEK_SET );
|
||
|
|
||
|
MidiPtr = ( char * )malloc( size );
|
||
|
if ( MidiPtr == NULL )
|
||
|
{
|
||
|
printf( "Out of memory while reading '%s'.\n", filename );
|
||
|
exit( 1 );
|
||
|
}
|
||
|
|
||
|
if ( fread( MidiPtr, size, 1, in ) != 1 )
|
||
|
{
|
||
|
printf( "Unexpected end of file while reading '%s'.\n", filename );
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
fclose( in );
|
||
|
|
||
|
return( MidiPtr );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*---------------------------------------------------------------------
|
||
|
Function: GetUserText
|
||
|
|
||
|
Checks if the specified string is present in the command line
|
||
|
and returns a pointer to the text following it.
|
||
|
---------------------------------------------------------------------*/
|
||
|
|
||
|
char *GetUserText
|
||
|
(
|
||
|
const char *parameter
|
||
|
)
|
||
|
|
||
|
{
|
||
|
int i;
|
||
|
int length;
|
||
|
char *text;
|
||
|
char *ptr;
|
||
|
|
||
|
extern int _argc;
|
||
|
extern char **_argv;
|
||
|
|
||
|
text = NULL;
|
||
|
length = strlen( parameter );
|
||
|
i = 1;
|
||
|
while( i < _argc )
|
||
|
{
|
||
|
ptr = _argv[ i ];
|
||
|
|
||
|
if ( ( strnicmp( parameter, ptr, length ) == 0 ) &&
|
||
|
( *( ptr + length ) == '=' ) )
|
||
|
{
|
||
|
text = ptr + length + 1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
return( text );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*---------------------------------------------------------------------
|
||
|
Function: CheckUserParm
|
||
|
|
||
|
Checks if the specified string is present in the command line.
|
||
|
---------------------------------------------------------------------*/
|
||
|
|
||
|
int CheckUserParm
|
||
|
(
|
||
|
const char *parameter
|
||
|
)
|
||
|
|
||
|
{
|
||
|
int i;
|
||
|
int found;
|
||
|
char *ptr;
|
||
|
|
||
|
extern int _argc;
|
||
|
extern char **_argv;
|
||
|
|
||
|
found = FALSE;
|
||
|
i = 1;
|
||
|
while( i < _argc )
|
||
|
{
|
||
|
ptr = _argv[ i ];
|
||
|
|
||
|
// Only check parameters preceded by - or /
|
||
|
if ( ( *ptr == '-' ) || ( *ptr == '/' ) )
|
||
|
{
|
||
|
ptr++;
|
||
|
if ( stricmp( parameter, ptr ) == 0 )
|
||
|
{
|
||
|
found = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
return( found );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*---------------------------------------------------------------------
|
||
|
Function: DefaultExtension
|
||
|
|
||
|
Checks if the specified filename contains an extension and adds
|
||
|
one if it doesn't.
|
||
|
---------------------------------------------------------------------*/
|
||
|
|
||
|
void DefaultExtension
|
||
|
(
|
||
|
char *path,
|
||
|
char *extension
|
||
|
)
|
||
|
|
||
|
{
|
||
|
char *src;
|
||
|
|
||
|
//
|
||
|
// if path doesn't have a .EXT, append extension
|
||
|
// (extension should include the .)
|
||
|
//
|
||
|
src = path + strlen( path ) - 1;
|
||
|
|
||
|
while( ( *src != '\\' ) && ( src != path ) )
|
||
|
{
|
||
|
if ( *src == '.' )
|
||
|
{
|
||
|
// it has an extension
|
||
|
return;
|
||
|
}
|
||
|
src--;
|
||
|
}
|
||
|
|
||
|
strcat( path, extension );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*---------------------------------------------------------------------
|
||
|
Function: TurnOffTextCursor
|
||
|
|
||
|
Turns the cursor off.
|
||
|
---------------------------------------------------------------------*/
|
||
|
|
||
|
void TurnOffTextCursor
|
||
|
(
|
||
|
void
|
||
|
)
|
||
|
|
||
|
{
|
||
|
union REGS regs;
|
||
|
|
||
|
regs.w.ax = 0x0100;
|
||
|
regs.w.cx = 0x2000;
|
||
|
#ifdef __FLAT__
|
||
|
int386(0x10,®s,®s);
|
||
|
#else
|
||
|
int86(0x10,®s,®s);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
/*---------------------------------------------------------------------
|
||
|
Function: TurnOnTextCursor
|
||
|
|
||
|
Turns the cursor on.
|
||
|
---------------------------------------------------------------------*/
|
||
|
|
||
|
void TurnOnTextCursor
|
||
|
(
|
||
|
void
|
||
|
)
|
||
|
|
||
|
{
|
||
|
union REGS regs;
|
||
|
|
||
|
regs.w.ax = 0x0100;
|
||
|
regs.w.cx = 0x0708;
|
||
|
#ifdef __FLAT__
|
||
|
int386(0x10,®s,®s);
|
||
|
#else
|
||
|
int86(0x10,®s,®s);
|
||
|
#endif
|
||
|
}
|