comparison playsound/playsound.c @ 383:818f9af97a19

Cleanups, FIXME removals, and better command line handling.
author Ryan C. Gordon <icculus@icculus.org>
date Fri, 05 Jul 2002 20:05:03 +0000
parents cbb15ecf423a
children 3bd96d2d553c
comparison
equal deleted inserted replaced
382:ce998ee6194f 383:818f9af97a19
55 #define DEFAULT_AUDIOBUF 4096 55 #define DEFAULT_AUDIOBUF 4096
56 56
57 #define PLAYSOUND_VER_MAJOR 0 57 #define PLAYSOUND_VER_MAJOR 0
58 #define PLAYSOUND_VER_MINOR 1 58 #define PLAYSOUND_VER_MINOR 1
59 #define PLAYSOUND_VER_PATCH 5 59 #define PLAYSOUND_VER_PATCH 5
60
61
62 static const char *option_list[] =
63 {
64 "--rate", "n Playback at sample rate of n HZ.",
65 "--format", "fmt Playback in fmt format (see below).",
66 "--channels", "n Playback on n channels (1 or 2).",
67 "--decodebuf", "n Buffer n decoded bytes at a time (default 16384).",
68 "--audiobuf", "n Buffer n samples to audio device (default 4096).",
69 "--volume", "n Playback volume multiplier (default 1.0).",
70 "--stdin", "[ext] Read from stdin (treat data as format [ext])",
71 "--version", " Display version information and exit.",
72 "--decoders", " List supported data formats and exit.",
73 "--predecode", " Decode entire sample before playback.",
74 "--loop", "n Loop playback n times.",
75 "--seek", "list List of seek points and playback durations.",
76 "--credits", " Shameless promotion.",
77 "--help", " Display this information and exit.",
78 NULL, NULL
79 };
80
60 81
61 static void output_versions(const char *argv0) 82 static void output_versions(const char *argv0)
62 { 83 {
63 Sound_Version compiled; 84 Sound_Version compiled;
64 Sound_Version linked; 85 Sound_Version linked;
118 } /* output_decoders */ 139 } /* output_decoders */
119 140
120 141
121 static void output_usage(const char *argv0) 142 static void output_usage(const char *argv0)
122 { 143 {
144 const char **i = option_list;
145
123 fprintf(stderr, 146 fprintf(stderr,
124 "USAGE: %s [...options...] [soundFile1] ... [soundFileN]\n" 147 "USAGE: %s [...options...] [soundFile1] ... [soundFileN]\n"
125 "\n" 148 "\n"
126 " Options:\n" 149 " Options:\n",
127 " --rate n Playback at sample rate of n HZ.\n" 150 argv0);
128 " --format fmt Playback in fmt format (see below).\n" 151
129 " --channels n Playback on n channels (1 or 2).\n" 152 while (*i != NULL)
130 " --decodebuf n Buffer n decoded bytes at a time (default %d).\n" 153 {
131 " --audiobuf n Buffer n samples to audio device (default %d).\n" 154 const char *option = *(i++);
132 " --volume n Playback volume multiplier (default 1.0).\n" 155 const char *optiondesc = *(i++);
133 " --stdin [ext] Read from stdin (treat data as format [ext])\n" 156 fprintf(stderr, " %s %s\n", option, optiondesc);
134 " --version Display version information and exit.\n" 157 } /* while */
135 " --decoders List supported data formats and exit.\n" 158
136 " --predecode Decode entire sample before playback.\n" 159 fprintf(stderr,
137 " --loop n Loop playback n times.\n"
138 " --seek list List of seek points and playback durations.\n"
139 " --credits Shameless promotion.\n"
140 " --help Display this information and exit.\n"
141 "\n" 160 "\n"
142 " Valid arguments to the --format option are:\n" 161 " Valid arguments to the --format option are:\n"
143 " U8 Unsigned 8-bit.\n" 162 " U8 Unsigned 8-bit.\n"
144 " S8 Signed 8-bit.\n" 163 " S8 Signed 8-bit.\n"
145 " U16LSB Unsigned 16-bit (least significant byte first).\n" 164 " U16LSB Unsigned 16-bit (least significant byte first).\n"
155 " The third mm:SS:ss is another seek after the duration of\n" 174 " The third mm:SS:ss is another seek after the duration of\n"
156 " playback has completed. If the final playback duration is\n" 175 " playback has completed. If the final playback duration is\n"
157 " omitted, playback continues until the end of the file.\n" 176 " omitted, playback continues until the end of the file.\n"
158 " The \"mm\" and \"SS\" portions may be omitted. --loop\n" 177 " The \"mm\" and \"SS\" portions may be omitted. --loop\n"
159 " and --seek can coexist.\n" 178 " and --seek can coexist.\n"
160 "\n", 179 "\n");
161 argv0, DEFAULT_DECODEBUF, DEFAULT_AUDIOBUF);
162 } /* output_usage */ 180 } /* output_usage */
163 181
164 182
165 static void output_credits(void) 183 static void output_credits(void)
166 { 184 {
313 } /* sigint_catcher */ 331 } /* sigint_catcher */
314 #endif 332 #endif
315 333
316 334
317 /* global decoding state. */ 335 /* global decoding state. */
318 /* !!! FIXME: Put this in a struct and pass a pointer to it as the 336 typedef struct
319 * !!! FIXME: audio callback's argument. This will clean up the 337 {
320 * !!! FIXME: namespace and let me reinitialize this for each file in 338 Uint8 *decoded_ptr;
321 * !!! FIXME: a cleaner way. 339 Uint32 decoded_bytes;
322 */ 340 int predecode;
323 static volatile Uint8 *decoded_ptr = NULL; 341 int looping;
324 static volatile Uint32 decoded_bytes = 0; 342 int wants_volume_change;
325 static volatile int predecode = 0; 343 float volume;
326 static volatile int looping = 0; 344 Uint32 total_seeks;
327 static volatile int wants_volume_change = 0; 345 Uint32 *seek_list;
328 static volatile float volume = 1.0; 346 Uint32 seek_index;
329 static volatile Uint32 total_seeks = 0; 347 Sint32 bytes_before_next_seek;
330 static volatile Uint32 *seek_list = NULL; 348 } playsound_global_state;
331 static volatile Uint32 seek_index = 0; 349
332 static volatile Sint32 bytes_before_next_seek = -1; 350 static volatile playsound_global_state global_state;
351
333 352
334 static Uint32 cvtMsToBytePos(Sound_AudioInfo *info, Uint32 ms) 353 static Uint32 cvtMsToBytePos(Sound_AudioInfo *info, Uint32 ms)
335 { 354 {
336 /* "frames" == "sample frames" */ 355 /* "frames" == "sample frames" */
337 float frames_per_ms = ((float) info->rate) / 1000.0; 356 float frames_per_ms = ((float) info->rate) / 1000.0;
341 } /* cvtMsToBytePos */ 360 } /* cvtMsToBytePos */
342 361
343 362
344 static void do_seek(Sound_Sample *sample) 363 static void do_seek(Sound_Sample *sample)
345 { 364 {
365 Uint32 *seek_list = global_state.seek_list;
366 Uint32 seek_index = global_state.seek_index;
367 Uint32 total_seeks = global_state.total_seeks;
368
346 fprintf(stdout, "Seeking to %.2d:%.2d:%.4d...\n", 369 fprintf(stdout, "Seeking to %.2d:%.2d:%.4d...\n",
347 (int) ((seek_list[seek_index] / 1000) / 60), 370 (int) ((seek_list[seek_index] / 1000) / 60),
348 (int) ((seek_list[seek_index] / 1000) % 60), 371 (int) ((seek_list[seek_index] / 1000) % 60),
349 (int) ((seek_list[seek_index] % 1000))); 372 (int) ((seek_list[seek_index] % 1000)));
350 373
351 if (predecode) 374 if (global_state.predecode)
352 { 375 {
353 Uint32 pos = cvtMsToBytePos(&sample->desired, seek_list[seek_index]); 376 Uint32 pos = cvtMsToBytePos(&sample->desired, seek_list[seek_index]);
354 if (pos > sample->buffer_size) 377 if (pos > sample->buffer_size)
355 { 378 {
356 fprintf(stderr, "Seek past end of predecoded buffer.\n"); 379 fprintf(stderr, "Seek past end of predecoded buffer.\n");
357 done_flag = 1; 380 done_flag = 1;
358 } /* if */ 381 } /* if */
359 else 382 else
360 { 383 {
361 decoded_ptr = (((Uint8 *) sample->buffer) + pos); 384 global_state.decoded_ptr = (((Uint8 *) sample->buffer) + pos);
362 decoded_bytes = sample->buffer_size - pos; 385 global_state.decoded_bytes = sample->buffer_size - pos;
363 } /* else */ 386 } /* else */
364 } /* if */ 387 } /* if */
365 else 388 else
366 { 389 {
367 if (!Sound_Seek(sample, seek_list[seek_index])) 390 if (!Sound_Seek(sample, seek_list[seek_index]))
371 } /* if */ 394 } /* if */
372 } /* else */ 395 } /* else */
373 396
374 seek_index++; 397 seek_index++;
375 if (seek_index >= total_seeks) 398 if (seek_index >= total_seeks)
376 bytes_before_next_seek = -1; /* no more seeks. */ 399 global_state.bytes_before_next_seek = -1; /* no more seeks. */
377 else 400 else
378 { 401 {
379 bytes_before_next_seek = cvtMsToBytePos(&sample->desired, 402 global_state.bytes_before_next_seek = cvtMsToBytePos(&sample->desired,
380 seek_list[seek_index]); 403 seek_list[seek_index]);
381 seek_index++; 404 seek_index++;
382 } /* else */ 405 } /* else */
406
407 global_state.seek_index = seek_index;
383 } /* do_seek */ 408 } /* do_seek */
384 409
385 410
386 /* 411 /*
387 * This updates (decoded_bytes) and (decoded_ptr) with more audio data, 412 * This updates (decoded_bytes) and (decoded_ptr) with more audio data,
389 */ 414 */
390 static int read_more_data(Sound_Sample *sample) 415 static int read_more_data(Sound_Sample *sample)
391 { 416 {
392 if (done_flag) /* probably a sigint; stop trying to read. */ 417 if (done_flag) /* probably a sigint; stop trying to read. */
393 { 418 {
394 decoded_bytes = 0; 419 global_state.decoded_bytes = 0;
395 return(0); 420 return(0);
396 } /* if */ 421 } /* if */
397 422
398 if ((bytes_before_next_seek >= 0) && 423 if ((global_state.bytes_before_next_seek >= 0) &&
399 (decoded_bytes > bytes_before_next_seek)) 424 (global_state.decoded_bytes > global_state.bytes_before_next_seek))
400 { 425 {
401 decoded_bytes = bytes_before_next_seek; 426 global_state.decoded_bytes = global_state.bytes_before_next_seek;
402 } /* if */ 427 } /* if */
403 428
404 if (decoded_bytes > 0) /* don't need more data; just return. */ 429 if (global_state.decoded_bytes > 0) /* don't need more data; just return. */
405 return(decoded_bytes); 430 return(global_state.decoded_bytes);
406 431
407 /* Need more audio data. See if we're supposed to seek... */ 432 /* Need more audio data. See if we're supposed to seek... */
408 if ((bytes_before_next_seek == 0) && (seek_index < total_seeks)) 433 if ((global_state.bytes_before_next_seek == 0) &&
434 (global_state.seek_index < global_state.total_seeks))
409 { 435 {
410 do_seek(sample); /* do it, baby! */ 436 do_seek(sample); /* do it, baby! */
411 return(read_more_data(sample)); /* handle loops conditions. */ 437 return(read_more_data(sample)); /* handle loops conditions. */
412 } /* if */ 438 } /* if */
413 439
414 /* See if there's more to be read... */ 440 /* See if there's more to be read... */
415 if ( (bytes_before_next_seek != 0) && 441 if ( (global_state.bytes_before_next_seek != 0) &&
416 (!(sample->flags & (SOUND_SAMPLEFLAG_ERROR | SOUND_SAMPLEFLAG_EOF))) ) 442 (!(sample->flags & (SOUND_SAMPLEFLAG_ERROR | SOUND_SAMPLEFLAG_EOF))) )
417 { 443 {
418 decoded_bytes = Sound_Decode(sample); 444 global_state.decoded_bytes = Sound_Decode(sample);
419 if (sample->flags & SOUND_SAMPLEFLAG_ERROR) 445 if (sample->flags & SOUND_SAMPLEFLAG_ERROR)
420 { 446 {
421 fprintf(stderr, "Error in decoding sound file!\n" 447 fprintf(stderr, "Error in decoding sound file!\n"
422 " reason: [%s].\n", Sound_GetError()); 448 " reason: [%s].\n", Sound_GetError());
423 } /* if */ 449 } /* if */
424 450
425 decoded_ptr = sample->buffer; 451 global_state.decoded_ptr = sample->buffer;
426 return(read_more_data(sample)); /* handle loops conditions. */ 452 return(read_more_data(sample)); /* handle loops conditions. */
427 } /* if */ 453 } /* if */
428 454
429 /* No more to be read from stream, but we may want to loop the sample. */ 455 /* No more to be read from stream, but we may want to loop the sample. */
430 456
431 if (!looping) 457 if (!global_state.looping)
432 return(0); 458 return(0);
433 459
434 looping--; 460 global_state.looping--;
435 461
436 seek_index = 0; 462 global_state.seek_index = 0;
437 bytes_before_next_seek = (total_seeks > 0) ? 0 : -1; 463 global_state.bytes_before_next_seek =
464 (global_state.total_seeks > 0) ? 0 : -1;
438 465
439 /* we just need to point predecoded samples to the start of the buffer. */ 466 /* we just need to point predecoded samples to the start of the buffer. */
440 if (predecode) 467 if (global_state.predecode)
441 { 468 {
442 decoded_bytes = sample->buffer_size; 469 global_state.decoded_bytes = sample->buffer_size;
443 decoded_ptr = sample->buffer; 470 global_state.decoded_ptr = sample->buffer;
444 } /* if */ 471 } /* if */
445 else 472 else
446 { 473 {
447 Sound_Rewind(sample); /* error is checked in recursion. */ 474 Sound_Rewind(sample); /* error is checked in recursion. */
448 } /* else */ 475 } /* else */
457 int i; 484 int i;
458 Uint16 *u16src = NULL; 485 Uint16 *u16src = NULL;
459 Uint16 *u16dst = NULL; 486 Uint16 *u16dst = NULL;
460 Sint16 *s16src = NULL; 487 Sint16 *s16src = NULL;
461 Sint16 *s16dst = NULL; 488 Sint16 *s16dst = NULL;
462 489 float volume = global_state.volume;
463 if (!wants_volume_change) 490
491 if (!global_state.wants_volume_change)
464 { 492 {
465 memcpy(dst, src, len); 493 memcpy(dst, src, len);
466 return; 494 return;
467 } 495 } /* if */
468 496
469 /* !!! FIXME: This would be more efficient with a lookup table. */ 497 /* !!! FIXME: This would be more efficient with a lookup table. */
470 switch (sample->desired.format) 498 switch (sample->desired.format)
471 { 499 {
472 case AUDIO_U8: 500 case AUDIO_U8:
484 u16dst = (Uint16 *) dst; 512 u16dst = (Uint16 *) dst;
485 for (i = 0; i < len; i += sizeof (Uint16), u16src++, u16dst++) 513 for (i = 0; i < len; i += sizeof (Uint16), u16src++, u16dst++)
486 { 514 {
487 *u16dst = (Uint16) (((float) (SDL_SwapLE16(*u16src))) * volume); 515 *u16dst = (Uint16) (((float) (SDL_SwapLE16(*u16src))) * volume);
488 *u16dst = SDL_SwapLE16(*u16dst); 516 *u16dst = SDL_SwapLE16(*u16dst);
489 } 517 } /* for */
490 break; 518 break;
491 519
492 case AUDIO_S16LSB: 520 case AUDIO_S16LSB:
493 s16src = (Sint16 *) src; 521 s16src = (Sint16 *) src;
494 s16dst = (Sint16 *) dst; 522 s16dst = (Sint16 *) dst;
495 for (i = 0; i < len; i += sizeof (Sint16), s16src++, s16dst++) 523 for (i = 0; i < len; i += sizeof (Sint16), s16src++, s16dst++)
496 { 524 {
497 *s16dst = (Sint16) (((float) (SDL_SwapLE16(*s16src))) * volume); 525 *s16dst = (Sint16) (((float) (SDL_SwapLE16(*s16src))) * volume);
498 *s16dst = SDL_SwapLE16(*s16dst); 526 *s16dst = SDL_SwapLE16(*s16dst);
499 } 527 } /* for */
500 break; 528 break;
501 529
502 case AUDIO_U16MSB: 530 case AUDIO_U16MSB:
503 u16src = (Uint16 *) src; 531 u16src = (Uint16 *) src;
504 u16dst = (Uint16 *) dst; 532 u16dst = (Uint16 *) dst;
505 for (i = 0; i < len; i += sizeof (Uint16), u16src++, u16dst++) 533 for (i = 0; i < len; i += sizeof (Uint16), u16src++, u16dst++)
506 { 534 {
507 *u16dst = (Uint16) (((float) (SDL_SwapBE16(*u16src))) * volume); 535 *u16dst = (Uint16) (((float) (SDL_SwapBE16(*u16src))) * volume);
508 *u16dst = SDL_SwapBE16(*u16dst); 536 *u16dst = SDL_SwapBE16(*u16dst);
509 } 537 } /* for */
510 break; 538 break;
511 539
512 case AUDIO_S16MSB: 540 case AUDIO_S16MSB:
513 s16src = (Sint16 *) src; 541 s16src = (Sint16 *) src;
514 s16dst = (Sint16 *) dst; 542 s16dst = (Sint16 *) dst;
515 for (i = 0; i < len; i += sizeof (Sint16), s16src++, s16dst++) 543 for (i = 0; i < len; i += sizeof (Sint16), s16src++, s16dst++)
516 { 544 {
517 *s16dst = (Sint16) (((float) (SDL_SwapBE16(*s16src))) * volume); 545 *s16dst = (Sint16) (((float) (SDL_SwapBE16(*s16src))) * volume);
518 *s16dst = SDL_SwapBE16(*s16dst); 546 *s16dst = SDL_SwapBE16(*s16dst);
519 } 547 } /* for */
520 break; 548 break;
521 } 549 } /* switch */
522 } 550 } /* memcpy_with_volume */
523 551
524 552
525 static void audio_callback(void *userdata, Uint8 *stream, int len) 553 static void audio_callback(void *userdata, Uint8 *stream, int len)
526 { 554 {
527 Sound_Sample *sample = (Sound_Sample *) userdata; 555 Sound_Sample *sample = (Sound_Sample *) userdata;
540 } /* if */ 568 } /* if */
541 569
542 /* decoded_bytes and decoder_ptr are updated as necessary... */ 570 /* decoded_bytes and decoder_ptr are updated as necessary... */
543 571
544 cpysize = len - bw; 572 cpysize = len - bw;
545 if (cpysize > decoded_bytes) 573 if (cpysize > global_state.decoded_bytes)
546 cpysize = decoded_bytes; 574 cpysize = global_state.decoded_bytes;
547 575
548 if (cpysize > 0) 576 if (cpysize > 0)
549 { 577 {
550 memcpy_with_volume(sample, stream + bw, 578 memcpy_with_volume(sample, stream + bw,
551 (Uint8 *) decoded_ptr, cpysize); 579 (Uint8 *) global_state.decoded_ptr,
580 cpysize);
581
552 bw += cpysize; 582 bw += cpysize;
553 decoded_ptr += cpysize; 583 global_state.decoded_ptr += cpysize;
554 decoded_bytes -= cpysize; 584 global_state.decoded_bytes -= cpysize;
555 if (bytes_before_next_seek >= 0) 585 if (global_state.bytes_before_next_seek >= 0)
556 bytes_before_next_seek -= cpysize; 586 global_state.bytes_before_next_seek -= cpysize;
557 } /* if */ 587 } /* if */
558 } /* while */ 588 } /* while */
559 } /* audio_callback */ 589 } /* audio_callback */
560 590
561 591
613 return; 643 return;
614 } /* if */ 644 } /* if */
615 645
616 strcpy(list, _list); 646 strcpy(list, _list);
617 647
618 if (seek_list != NULL) 648 if (global_state.seek_list != NULL)
619 free((void *) seek_list); 649 free((void *) global_state.seek_list);
620 650
621 total_seeks = count_seek_list(list); 651 global_state.total_seeks = count_seek_list(list);
622 seek_list = (Uint32 *) malloc(total_seeks * sizeof (Uint32)); 652
623 if (seek_list == NULL) 653 global_state.seek_list =
654 (Uint32 *) malloc(global_state.total_seeks * sizeof (Uint32));
655
656 if (global_state.seek_list == NULL)
624 { 657 {
625 fprintf(stderr, "malloc() failed. Skipping seek list.\n"); 658 fprintf(stderr, "malloc() failed. Skipping seek list.\n");
626 total_seeks = 0; 659 global_state.total_seeks = 0;
627 return; 660 return;
628 } /* if */ 661 } /* if */
629 662
630 for (i = 0; i < total_seeks; i++) 663 for (i = 0; i < global_state.total_seeks; i++)
631 { 664 {
632 char *ptr = strchr(list, ';'); 665 char *ptr = strchr(list, ';');
633 if (ptr != NULL) 666 if (ptr != NULL)
634 *ptr = '\0'; 667 *ptr = '\0';
635 seek_list[i] = parse_time_str(list); 668 global_state.seek_list[i] = parse_time_str(list);
636 list = ptr + 1; 669 list = ptr + 1;
637 } /* for */ 670 } /* for */
671
672 global_state.bytes_before_next_seek = 0;
638 673
639 free(save_list); 674 free(save_list);
640 } /* parse_seek_list */ 675 } /* parse_seek_list */
641 676
642 677
656 return AUDIO_S16MSB; 691 return AUDIO_S16MSB;
657 return 0; 692 return 0;
658 } /* str_to_fmt */ 693 } /* str_to_fmt */
659 694
660 695
696 static int valid_cmdline(int argc, char **argv)
697 {
698 int i;
699
700 if (argc < 2) /* no command line? Show help text and quit. */
701 {
702 output_usage(argv[0]);
703 return(0);
704 } /* if */
705
706 /* Make sure all command line options are valid. */
707 for (i = 1; i < argc; i++)
708 {
709 const char **opts = option_list;
710
711 if (strncmp(argv[i], "--", 2) != 0) /* not an option; skip it. */
712 continue;
713
714 while (*opts != NULL)
715 {
716 if (strcmp(argv[i], *(opts++)) == 0)
717 break;
718
719 opts++; /* skip option description. */
720 } /* else */
721
722 if (*opts == NULL) /* didn't find it in option_list... */
723 {
724 fprintf(stderr, "unknown option: \"%s\"\n", argv[i]);
725 return(0);
726 } /* if */
727 } /* for */
728
729 return(1); /* everything appears to be in order. */
730 } /* valid_cmdline */
731
732
661 int main(int argc, char **argv) 733 int main(int argc, char **argv)
662 { 734 {
663 Sound_AudioInfo sound_desired; 735 Sound_AudioInfo sound_desired;
664 Uint32 audio_buffersize = DEFAULT_AUDIOBUF;
665 Uint32 decode_buffersize = DEFAULT_DECODEBUF;
666 SDL_AudioSpec sdl_desired; 736 SDL_AudioSpec sdl_desired;
667 SDL_AudioSpec sdl_actual; 737 SDL_AudioSpec sdl_actual;
738 Uint32 audio_buffersize;
739 Uint32 decode_buffersize;
668 Sound_Sample *sample; 740 Sound_Sample *sample;
669 int use_specific_audiofmt = 0; 741 int use_specific_audiofmt = 0;
670 int i; 742 int i;
671 int delay; 743 int delay;
672 int new_sample = 1; 744 int new_sample = 1;
745 Uint32 sdl_init_flags = SDL_INIT_AUDIO;
746
747 #if ENABLE_EVENTS
748 SDL_Surface *screen = NULL;
749 SDL_Event event;
750
751 sdl_init_flags |= SDL_INIT_VIDEO;
752 #endif
673 753
674 #ifdef HAVE_SETBUF 754 #ifdef HAVE_SETBUF
675 setbuf(stdout, NULL); 755 setbuf(stdout, NULL);
676 setbuf(stderr, NULL); 756 setbuf(stderr, NULL);
677 #endif 757 #endif
678 758
679 if (argc < 2) 759 if (!valid_cmdline(argc, argv))
680 {
681 output_usage(argv[0]);
682 return(42); 760 return(42);
683 } /* if */ 761
684 762 /* Handle some command lines upfront. */
685 /* Check some command lines upfront. */
686 for (i = 0; i < argc; i++) 763 for (i = 0; i < argc; i++)
687 { 764 {
688 if (strncmp(argv[i], "--", 2) != 0) 765 if (strncmp(argv[i], "--", 2) != 0)
689 continue; 766 continue;
690 767
718 795
719 output_decoders(); 796 output_decoders();
720 Sound_Quit(); 797 Sound_Quit();
721 return(0); 798 return(0);
722 } /* else if */ 799 } /* else if */
723
724 /* !!! FIXME: Verify other --arguments are valid. */
725 #if 0
726 else
727 {
728 fprintf(stderr, "unknown option: \"%s\"\n", argv[i]);
729 return(42);
730 } /* else */
731 #endif
732 } /* for */ 800 } /* for */
733 801
734 if (!init_archive(argv[0])) 802 if (!init_archive(argv[0]))
735 return(42); 803 return(42);
736 804
737 if (SDL_Init(SDL_INIT_AUDIO) == -1) 805 if (SDL_Init(sdl_init_flags) == -1)
738 { 806 {
739 fprintf(stderr, "SDL_Init(SDL_INIT_AUDIO) failed!\n" 807 fprintf(stderr, "SDL_Init() failed!\n"
740 " reason: [%s].\n", SDL_GetError()); 808 " reason: [%s].\n", SDL_GetError());
741 return(42); 809 return(42);
742 } /* if */ 810 } /* if */
743 811
744 if (!Sound_Init()) 812 if (!Sound_Init())
751 819
752 #if HAVE_SIGNAL_H 820 #if HAVE_SIGNAL_H
753 signal(SIGINT, sigint_catcher); 821 signal(SIGINT, sigint_catcher);
754 #endif 822 #endif
755 823
824 #if ENABLE_EVENTS
825 screen = SDL_SetVideoMode(320, 240, 8, 0);
826 assert(screen != NULL);
827 #endif
828
756 for (i = 1; i < argc; i++) 829 for (i = 1; i < argc; i++)
757 { 830 {
758 char *filename = NULL; 831 char *filename = NULL;
759 832
760 /* !!! FIXME: Go read gripe about all the global variables. */
761 /* set variables back to defaults for next file... */ 833 /* set variables back to defaults for next file... */
762 if (new_sample) 834 if (new_sample)
763 { 835 {
764 new_sample = 0; 836 if (global_state.seek_list != NULL)
765 memset(&sound_desired, '\0', sizeof (sound_desired)); 837 free((void *) global_state.seek_list);
766 done_flag = 0; 838
767 decoded_ptr = NULL; 839 memset((void *) &global_state, '\0', sizeof (global_state));
768 decoded_bytes = 0; 840 global_state.volume = 1.0;
769 predecode = 0; 841 global_state.bytes_before_next_seek = -1;
770 looping = 0;
771 audio_buffersize = DEFAULT_AUDIOBUF; 842 audio_buffersize = DEFAULT_AUDIOBUF;
772 decode_buffersize = DEFAULT_DECODEBUF; 843 decode_buffersize = DEFAULT_DECODEBUF;
773 sample = NULL;
774 use_specific_audiofmt = 0;
775 wants_volume_change = 0;
776 volume = 1.0;
777 if (seek_list != NULL)
778 {
779 free((void *) seek_list);
780 seek_list = NULL;
781 } /* if */
782 total_seeks = 0;
783 seek_index = 0;
784 bytes_before_next_seek = -1;
785 } /* if */ 844 } /* if */
786 845
787 if (strcmp(argv[i], "--rate") == 0 && argc > i + 1) 846 if (strcmp(argv[i], "--rate") == 0 && argc > i + 1)
788 { 847 {
789 use_specific_audiofmt = 1; 848 use_specific_audiofmt = 1;
830 decode_buffersize = atoi(argv[++i]); 889 decode_buffersize = atoi(argv[++i]);
831 } /* else if */ 890 } /* else if */
832 891
833 else if (strcmp(argv[i], "--volume") == 0 && argc > i + 1) 892 else if (strcmp(argv[i], "--volume") == 0 && argc > i + 1)
834 { 893 {
835 volume = atof(argv[++i]); 894 global_state.volume = atof(argv[++i]);
836 if (volume != 1.0) 895 if (global_state.volume != 1.0)
837 wants_volume_change = 1; 896 global_state.wants_volume_change = 1;
838 } /* else if */ 897 } /* else if */
839 898
840 else if (strcmp(argv[i], "--predecode") == 0) 899 else if (strcmp(argv[i], "--predecode") == 0)
841 { 900 {
842 predecode = 1; 901 global_state.predecode = 1;
843 } /* else if */ 902 } /* else if */
844 903
845 else if (strcmp(argv[i], "--loop") == 0) 904 else if (strcmp(argv[i], "--loop") == 0)
846 { 905 {
847 looping = atoi(argv[++i]); 906 global_state.looping = atoi(argv[++i]);
848 } /* else if */ 907 } /* else if */
849 908
850 else if (strcmp(argv[i], "--seek") == 0) 909 else if (strcmp(argv[i], "--seek") == 0)
851 { 910 {
852 parse_seek_list(argv[++i]); 911 parse_seek_list(argv[++i]);
866 decode_buffersize); 925 decode_buffersize);
867 } /* if */ 926 } /* if */
868 927
869 else if (strncmp(argv[i], "--", 2) == 0) 928 else if (strncmp(argv[i], "--", 2) == 0)
870 { 929 {
871 /* ignore it. */ 930 /* ignore it, since it was handled at startup. */
872 } /* else if */ 931 } /* else if */
873 932
874 else 933 else
875 { 934 {
876 filename = argv[i]; 935 filename = argv[i];
897 " reason: [%s].\n", 956 " reason: [%s].\n",
898 filename, Sound_GetError()); 957 filename, Sound_GetError());
899 continue; 958 continue;
900 } /* if */ 959 } /* if */
901 960
902 if (total_seeks > 0) 961 if (global_state.total_seeks > 0)
903 { 962 {
904 if ((!predecode) && (!(sample->flags & SOUND_SAMPLEFLAG_CANSEEK))) 963 if ((!global_state.predecode) &&
964 (!(sample->flags & SOUND_SAMPLEFLAG_CANSEEK)))
905 { 965 {
906 fprintf(stderr, "Want seeks, but sample cannot handle it!\n"); 966 fprintf(stderr, "Want seeks, but sample cannot handle it!\n");
907 Sound_FreeSample(sample); 967 Sound_FreeSample(sample);
908 close_archive(filename); 968 close_archive(filename);
909 continue; 969 continue;
910 } /* if */ 970 } /* if */
911
912 bytes_before_next_seek = 0;
913 } /* if */ 971 } /* if */
914 972
915 /* 973 /*
916 * Unless explicitly specified, pick the format from the sound 974 * Unless explicitly specified, pick the format from the sound
917 * to be played. 975 * to be played.
942 return(42); 1000 return(42);
943 } /* if */ 1001 } /* if */
944 1002
945 fprintf(stdout, "Now playing [%s]...\n", filename); 1003 fprintf(stdout, "Now playing [%s]...\n", filename);
946 1004
947 if (predecode) 1005 if (global_state.predecode)
948 { 1006 {
949 fprintf(stdout, " predecoding..."); 1007 fprintf(stdout, " predecoding...");
950 decoded_bytes = Sound_DecodeAll(sample); 1008 global_state.decoded_bytes = Sound_DecodeAll(sample);
951 decoded_ptr = sample->buffer; 1009 global_state.decoded_ptr = sample->buffer;
952 if (sample->flags & SOUND_SAMPLEFLAG_ERROR) 1010 if (sample->flags & SOUND_SAMPLEFLAG_ERROR)
953 { 1011 {
954 fprintf(stderr, 1012 fprintf(stderr,
955 "Couldn't fully decode \"%s\"!\n" 1013 "Couldn't fully decode \"%s\"!\n"
956 " reason: [%s].\n" 1014 " reason: [%s].\n"
957 " (playing first %lu bytes of decoded data...)\n", 1015 " (playing first %lu bytes of decoded data...)\n",
958 filename, Sound_GetError(), decoded_bytes); 1016 filename, Sound_GetError(), global_state.decoded_bytes);
959 } /* if */ 1017 } /* if */
960 else 1018 else
961 { 1019 {
962 fprintf(stdout, "done.\n"); 1020 fprintf(stdout, "done.\n");
963 } /* else */ 1021 } /* else */
964 } /* if */ 1022 } /* if */
965 1023
966 SDL_PauseAudio(0); 1024 SDL_PauseAudio(0);
967 #if ENABLE_EVENTS 1025
968 {
969 SDL_Surface *screen;
970 SDL_Event event;
971
972 screen = SDL_SetVideoMode (320, 240, 8, 0);
973
974 while (!done_flag) {
975
976 SDL_Delay(1);
977 SDL_PollEvent (&event);
978
979 if (event.type == SDL_KEYDOWN) {
980
981 done_flag = 1;
982 break;
983 }
984
985 }
986 }
987 #endif /* ENABLE_EVENTS */
988 while (!done_flag) 1026 while (!done_flag)
989 { 1027 {
1028 #if ENABLE_EVENTS
1029 SDL_PollEvent(&event);
1030 if ((event.type == SDL_KEYDOWN) || (event.type == SDL_QUIT))
1031 done_flag = 1;
1032 #endif
1033
990 SDL_Delay(10); 1034 SDL_Delay(10);
991 } /* while */ 1035 } /* while */
1036
992 SDL_PauseAudio(1); 1037 SDL_PauseAudio(1);
993 1038
994 /* 1039 /*
995 * Sleep two buffers' worth of audio before closing, in order 1040 * Sleep two buffers' worth of audio before closing, in order
996 * to allow the playback to finish. This isn't always enough; 1041 * to allow the playback to finish. This isn't always enough;