PM.C 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /*
  2. Copyright (C) 1994-1995 Apogee Software, Ltd.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. /**********************************************************************
  16. module: PM.C
  17. author: James R. Dose
  18. date: January 16, 1994
  19. Simple music player.
  20. (c) Copyright 1994 James R. Dose. All Rights Reserved.
  21. **********************************************************************/
  22. #include <conio.h>
  23. #include <dos.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include "music.h"
  28. /*---------------------------------------------------------------------
  29. Function prototypes
  30. ---------------------------------------------------------------------*/
  31. void LoadTimbres( char *timbrefile );
  32. char *LoadMidi( char *filename );
  33. char *GetUserText( const char *parameter );
  34. int CheckUserParm( const char *parameter );
  35. void DefaultExtension( char *path, char *extension );
  36. void TurnOffTextCursor( void );
  37. void TurnOnTextCursor( void );
  38. #define TRUE ( 1 == 1 )
  39. #define FALSE ( !TRUE )
  40. #define NUMCARDS 10
  41. char *SoundCardNames[] =
  42. {
  43. "General Midi", "Sound Canvas", "Awe 32", "WaveBlaster",
  44. "SoundBlaster", "Pro AudioSpectrum", "Sound Man 16", "Adlib",
  45. "Ensoniq SoundScape", "Gravis UltraSound"
  46. };
  47. int SoundCardNums[] =
  48. {
  49. GenMidi, SoundCanvas, Awe32, WaveBlaster,
  50. SoundBlaster, ProAudioSpectrum, SoundMan16,
  51. Adlib, SoundScape, UltraSound
  52. };
  53. /*---------------------------------------------------------------------
  54. Function: main
  55. Sets up sound cards, calls the demo, and then cleans up.
  56. ---------------------------------------------------------------------*/
  57. void main
  58. (
  59. int argc,
  60. char *argv[]
  61. )
  62. {
  63. int card;
  64. int address;
  65. int status;
  66. char *SongPtr = NULL;
  67. char *ptr;
  68. char filename[ 128 ];
  69. char timbrefile[ 128 ];
  70. int gotopos = 0;
  71. int measure = 0;
  72. int beat = 0;
  73. int tick = 0;
  74. int time = 0;
  75. printf( "\nPM EMIDI Music Player Version 1.21 Copyright (c) 1996 by Jim Dose\n" );
  76. if ( ( CheckUserParm( "?" ) ) || ( argc < 2 ) )
  77. {
  78. int index;
  79. printf(
  80. "Usage: PM [ midifile ] CARD=[ card number ] MPU=[ port address in hex ]\n"
  81. " TIMBRE=[ timbre file ] TIME=[minutes:seconds:milliseconds]\n"
  82. " POSITION=[measure:beat:tick]\n\n"
  83. " card number = \n" );
  84. for( index = 0; index < NUMCARDS; index++ )
  85. {
  86. printf( " %d : %s\n", index, SoundCardNames[ index ] );
  87. }
  88. printf( "\n" );
  89. exit( 0 );
  90. }
  91. // Default is GenMidi
  92. card = 0;
  93. address = 0x330;
  94. ptr = getenv( "PM" );
  95. if ( ptr != NULL )
  96. {
  97. sscanf( ptr, "%d,%x", &card, &address );
  98. }
  99. ptr = GetUserText( "MPU" );
  100. if ( ptr != NULL )
  101. {
  102. sscanf( ptr, "%x", &address );
  103. }
  104. ptr = GetUserText( "TIMBRE" );
  105. if ( ptr != NULL )
  106. {
  107. sscanf( ptr, "%s", timbrefile );
  108. LoadTimbres( timbrefile );
  109. }
  110. ptr = GetUserText( "POSITION" );
  111. if ( ptr != NULL )
  112. {
  113. gotopos = 1;
  114. sscanf( ptr, "%d:%d:%d", &measure, &beat, &tick );
  115. }
  116. ptr = GetUserText( "TIME" );
  117. if ( ptr != NULL )
  118. {
  119. int minutes = 0;
  120. int seconds = 0;
  121. int milli = 0;
  122. gotopos = 2;
  123. sscanf( ptr, "%d:%d:%d", &minutes, &seconds, &milli );
  124. time = minutes * ( 60 * 1000 ) + seconds * 1000 + milli;
  125. }
  126. ptr = GetUserText( "CARD" );
  127. if ( ptr != NULL )
  128. {
  129. sscanf( ptr, "%d", &card );
  130. }
  131. if ( ( card < 0 ) || ( card >= NUMCARDS ) )
  132. {
  133. printf( "Value out of range for CARD: %d\n", card );
  134. }
  135. status = MUSIC_Init( SoundCardNums[ card ], address );
  136. if ( status != MUSIC_Ok )
  137. {
  138. printf( "Error - %s\n", MUSIC_ErrorString( status ) );
  139. exit( 1 );
  140. }
  141. strcpy( filename, argv[ 1 ] );
  142. DefaultExtension( filename, ".mid" );
  143. SongPtr = LoadMidi( filename );
  144. MUSIC_SetVolume( 255 );
  145. status = MUSIC_PlaySong( SongPtr, MUSIC_LoopSong );
  146. if ( status != MUSIC_Ok )
  147. {
  148. printf( "Error - %s\n", MUSIC_ErrorString( status ) );
  149. }
  150. else
  151. {
  152. char ch;
  153. songposition pos;
  154. if ( gotopos == 1 )
  155. {
  156. MUSIC_SetSongPosition( measure, beat, tick );
  157. }
  158. else if ( gotopos == 2 )
  159. {
  160. MUSIC_SetSongTime( time );
  161. }
  162. printf( "Playing file '%s'.\n\n", filename );
  163. printf( "Press F to advance one measure.\n"
  164. "Press R to rewind one measure.\n"
  165. "Press G to go to the selected position.\n"
  166. "Press ESCape to end.\n\n" );
  167. MUSIC_GetSongLength( &pos );
  168. printf( "Song length: time (m:s:ms) = %d:%d:%d, "
  169. "(measure:beat:tick) = %d:%d:%d\n\n",
  170. pos.milliseconds / (60*1000),
  171. ( pos.milliseconds / 1000 ) % 60,
  172. pos.milliseconds % 1000,
  173. pos.measure, pos.beat, pos.tick );
  174. ch = 0;
  175. TurnOffTextCursor();
  176. while( ch != 27 )
  177. {
  178. MUSIC_GetSongPosition( &pos );
  179. printf( "time (m:s:ms) = %d:%d:%d \t(measure:beat:tick) = %d:%d:%d \r",
  180. pos.milliseconds / (60*1000),
  181. ( pos.milliseconds / 1000 ) % 60,
  182. pos.milliseconds % 1000,
  183. pos.measure, pos.beat, pos.tick );
  184. fflush( stdout );
  185. if ( kbhit() )
  186. {
  187. ch = getch();
  188. if ( ( ch == 'G' ) || ( ch == 'g' ) )
  189. {
  190. if ( gotopos == 1 )
  191. {
  192. MUSIC_SetSongPosition( measure, beat, tick );
  193. }
  194. else
  195. {
  196. MUSIC_SetSongTime( time );
  197. }
  198. ch = 0;
  199. while( kbhit() )
  200. {
  201. getch();
  202. }
  203. }
  204. if ( ( ch == 'F' ) || ( ch == 'f' ) )
  205. {
  206. MUSIC_SetSongPosition( pos.measure + 1, 1, 0 );
  207. ch = 0;
  208. while( kbhit() )
  209. {
  210. getch();
  211. }
  212. }
  213. if ( ( ch == 'R' ) || ( ch == 'r' ) )
  214. {
  215. MUSIC_SetSongPosition( pos.measure - 1, 1, 0 );
  216. ch = 0;
  217. while( kbhit() )
  218. {
  219. getch();
  220. }
  221. }
  222. }
  223. }
  224. TurnOnTextCursor();
  225. MUSIC_StopSong();
  226. }
  227. free( SongPtr );
  228. MUSIC_Shutdown();
  229. printf( "\n" );
  230. }
  231. /*---------------------------------------------------------------------
  232. Function: LoadTimbres
  233. Loads the instruments from disk
  234. ---------------------------------------------------------------------*/
  235. void LoadTimbres
  236. (
  237. char *timbrefile
  238. )
  239. {
  240. FILE *in;
  241. long size;
  242. char *TimbrePtr;
  243. if ( ( in = fopen( timbrefile, "rb" ) ) == NULL )
  244. {
  245. printf( "Cannot open '%s' for read.\n", timbrefile );
  246. exit( 1 );
  247. }
  248. fseek( in, 0, SEEK_END );
  249. size = ftell( in );
  250. fseek( in, 0, SEEK_SET );
  251. TimbrePtr = ( char * )malloc( size );
  252. if ( TimbrePtr == NULL )
  253. {
  254. printf( "Out of memory while reading '%s'.\n", timbrefile );
  255. exit( 1 );
  256. }
  257. if ( fread( TimbrePtr, size, 1, in ) != 1 )
  258. {
  259. printf( "Unexpected end of file while reading '%s'.\n", timbrefile );
  260. exit(1);
  261. }
  262. fclose( in );
  263. MUSIC_RegisterTimbreBank( TimbrePtr );
  264. }
  265. /*---------------------------------------------------------------------
  266. Function: LoadMidi
  267. Loads the midi file from disk.
  268. ---------------------------------------------------------------------*/
  269. char *LoadMidi
  270. (
  271. char *filename
  272. )
  273. {
  274. FILE *in;
  275. long size;
  276. char *MidiPtr;
  277. if ( ( in = fopen( filename, "rb" ) ) == NULL )
  278. {
  279. printf( "Cannot open '%s' for read.\n", filename );
  280. exit( 1 );
  281. }
  282. fseek( in, 0, SEEK_END );
  283. size = ftell( in );
  284. fseek( in, 0, SEEK_SET );
  285. MidiPtr = ( char * )malloc( size );
  286. if ( MidiPtr == NULL )
  287. {
  288. printf( "Out of memory while reading '%s'.\n", filename );
  289. exit( 1 );
  290. }
  291. if ( fread( MidiPtr, size, 1, in ) != 1 )
  292. {
  293. printf( "Unexpected end of file while reading '%s'.\n", filename );
  294. exit(1);
  295. }
  296. fclose( in );
  297. return( MidiPtr );
  298. }
  299. /*---------------------------------------------------------------------
  300. Function: GetUserText
  301. Checks if the specified string is present in the command line
  302. and returns a pointer to the text following it.
  303. ---------------------------------------------------------------------*/
  304. char *GetUserText
  305. (
  306. const char *parameter
  307. )
  308. {
  309. int i;
  310. int length;
  311. char *text;
  312. char *ptr;
  313. extern int _argc;
  314. extern char **_argv;
  315. text = NULL;
  316. length = strlen( parameter );
  317. i = 1;
  318. while( i < _argc )
  319. {
  320. ptr = _argv[ i ];
  321. if ( ( strnicmp( parameter, ptr, length ) == 0 ) &&
  322. ( *( ptr + length ) == '=' ) )
  323. {
  324. text = ptr + length + 1;
  325. break;
  326. }
  327. i++;
  328. }
  329. return( text );
  330. }
  331. /*---------------------------------------------------------------------
  332. Function: CheckUserParm
  333. Checks if the specified string is present in the command line.
  334. ---------------------------------------------------------------------*/
  335. int CheckUserParm
  336. (
  337. const char *parameter
  338. )
  339. {
  340. int i;
  341. int found;
  342. char *ptr;
  343. extern int _argc;
  344. extern char **_argv;
  345. found = FALSE;
  346. i = 1;
  347. while( i < _argc )
  348. {
  349. ptr = _argv[ i ];
  350. // Only check parameters preceded by - or /
  351. if ( ( *ptr == '-' ) || ( *ptr == '/' ) )
  352. {
  353. ptr++;
  354. if ( stricmp( parameter, ptr ) == 0 )
  355. {
  356. found = TRUE;
  357. break;
  358. }
  359. }
  360. i++;
  361. }
  362. return( found );
  363. }
  364. /*---------------------------------------------------------------------
  365. Function: DefaultExtension
  366. Checks if the specified filename contains an extension and adds
  367. one if it doesn't.
  368. ---------------------------------------------------------------------*/
  369. void DefaultExtension
  370. (
  371. char *path,
  372. char *extension
  373. )
  374. {
  375. char *src;
  376. //
  377. // if path doesn't have a .EXT, append extension
  378. // (extension should include the .)
  379. //
  380. src = path + strlen( path ) - 1;
  381. while( ( *src != '\\' ) && ( src != path ) )
  382. {
  383. if ( *src == '.' )
  384. {
  385. // it has an extension
  386. return;
  387. }
  388. src--;
  389. }
  390. strcat( path, extension );
  391. }
  392. /*---------------------------------------------------------------------
  393. Function: TurnOffTextCursor
  394. Turns the cursor off.
  395. ---------------------------------------------------------------------*/
  396. void TurnOffTextCursor
  397. (
  398. void
  399. )
  400. {
  401. union REGS regs;
  402. regs.w.ax = 0x0100;
  403. regs.w.cx = 0x2000;
  404. #ifdef __FLAT__
  405. int386(0x10,&regs,&regs);
  406. #else
  407. int86(0x10,&regs,&regs);
  408. #endif
  409. }
  410. /*---------------------------------------------------------------------
  411. Function: TurnOnTextCursor
  412. Turns the cursor on.
  413. ---------------------------------------------------------------------*/
  414. void TurnOnTextCursor
  415. (
  416. void
  417. )
  418. {
  419. union REGS regs;
  420. regs.w.ax = 0x0100;
  421. regs.w.cx = 0x0708;
  422. #ifdef __FLAT__
  423. int386(0x10,&regs,&regs);
  424. #else
  425. int86(0x10,&regs,&regs);
  426. #endif
  427. }