Mercurial > SDL_sound_CoreAudio
comparison playsound/playsound.c @ 308:6a80b2f9c47c
Command line updates, added Darrell to the credits, and cleaned up other
stuff. --loop now takes a numeric value.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Wed, 24 Apr 2002 07:56:52 +0000 |
parents | 414cfef0978e |
children | 9e21cb0d3ae7 |
comparison
equal
deleted
inserted
replaced
307:eb7c929193dd | 308:6a80b2f9c47c |
---|---|
116 " --volume n Playback volume multiplier (default 1.0).\n" | 116 " --volume n Playback volume multiplier (default 1.0).\n" |
117 " --stdin [ext] Read from stdin (treat data as format [ext])\n" | 117 " --stdin [ext] Read from stdin (treat data as format [ext])\n" |
118 " --version Display version information and exit.\n" | 118 " --version Display version information and exit.\n" |
119 " --decoders List supported data formats and exit.\n" | 119 " --decoders List supported data formats and exit.\n" |
120 " --predecode Decode entire sample before playback.\n" | 120 " --predecode Decode entire sample before playback.\n" |
121 " --loop Loop playback until SIGINT.\n" | 121 " --loop n Loop playback n times. 0=forever.\n" |
122 | |
123 /*" --seek list List of seek points and playback durations.\n"*/ | |
124 | |
122 " --credits Shameless promotion.\n" | 125 " --credits Shameless promotion.\n" |
123 " --help Display this information and exit.\n" | 126 " --help Display this information and exit.\n" |
124 "\n" | 127 "\n" |
125 " Valid arguments to the --format option are:\n" | 128 " Valid arguments to the --format option are:\n" |
126 " U8 Unsigned 8-bit.\n" | 129 " U8 Unsigned 8-bit.\n" |
127 " S8 Signed 8-bit.\n" | 130 " S8 Signed 8-bit.\n" |
128 " U16LSB Unsigned 16-bit (least significant byte first).\n" | 131 " U16LSB Unsigned 16-bit (least significant byte first).\n" |
129 " U16MSB Unsigned 16-bit (most significant byte first).\n" | 132 " U16MSB Unsigned 16-bit (most significant byte first).\n" |
130 " S16LSB Signed 16-bit (least significant byte first).\n" | 133 " S16LSB Signed 16-bit (least significant byte first).\n" |
131 " S16MSB Signed 16-bit (most significant byte first).\n" | 134 " S16MSB Signed 16-bit (most significant byte first).\n" |
135 | |
136 /* | |
137 "\n" | |
138 " Valid arguments to the --seek options look like:\n" | |
139 " --seek=\"mm:ss;mm:ss;mm:ss\"\n" | |
140 " Where the first \"mm:ss\" is the position, in minutes and\n" | |
141 " seconds to seek to at start of playback. The second mm:ss\n" | |
142 " is how long to play audio from that point. The third mm:ss\n" | |
143 " is another seek after the duration of playback has completed.\n" | |
144 " If the final playback duration is omitted, playback continues\n" | |
145 " until the end of the file. --loop and --seek can coexist.\n" | |
146 */ | |
147 | |
132 "\n", | 148 "\n", |
133 argv0, DEFAULT_DECODEBUF, DEFAULT_AUDIOBUF); | 149 argv0, DEFAULT_DECODEBUF, DEFAULT_AUDIOBUF); |
134 } /* output_usage */ | 150 } /* output_usage */ |
135 | 151 |
136 | 152 |
142 "Public License, and you are welcome to change it and/or\n" | 158 "Public License, and you are welcome to change it and/or\n" |
143 "distribute copies of it under certain conditions. There is\n" | 159 "distribute copies of it under certain conditions. There is\n" |
144 "absolutely NO WARRANTY for playsound.\n" | 160 "absolutely NO WARRANTY for playsound.\n" |
145 "\n" | 161 "\n" |
146 " Written by Ryan C. Gordon, Torbjörn Andersson, Max Horn,\n" | 162 " Written by Ryan C. Gordon, Torbjörn Andersson, Max Horn,\n" |
147 " Tsuyoshi Iguchi, Tyler Montbriand, and a cast of thousands.\n" | 163 " Tsuyoshi Iguchi, Tyler Montbriand, Darrell Walisser,\n" |
164 " and a cast of thousands.\n" | |
148 "\n" | 165 "\n" |
149 " Website and source code: http://icculus.org/SDL_sound/\n" | 166 " Website and source code: http://icculus.org/SDL_sound/\n" |
150 "\n", | 167 "\n", |
151 PLAYSOUND_VER_MAJOR, PLAYSOUND_VER_MINOR, PLAYSOUND_VER_PATCH); | 168 PLAYSOUND_VER_MAJOR, PLAYSOUND_VER_MINOR, PLAYSOUND_VER_PATCH); |
152 } /* output_credits */ | 169 } /* output_credits */ |
235 } /* close_archive */ | 252 } /* close_archive */ |
236 | 253 |
237 | 254 |
238 static void deinit_archive(void) | 255 static void deinit_archive(void) |
239 { | 256 { |
240 #if SUPPORT_PHYSFS | 257 #if SUPPORT_PHYSFS |
241 PHYSFS_deinit(); | 258 PHYSFS_deinit(); |
242 #endif | 259 #endif |
243 } /* deinit_archive */ | 260 } /* deinit_archive */ |
244 | 261 |
245 | 262 |
246 | 263 |
247 static volatile int done_flag = 0; | 264 static volatile int done_flag = 0; |
270 done_flag = 1; | 287 done_flag = 1; |
271 } /* else */ | 288 } /* else */ |
272 } /* sigint_catcher */ | 289 } /* sigint_catcher */ |
273 | 290 |
274 | 291 |
292 /* global decoding state. */ | |
293 /* !!! FIXME: Put this in a struct and pass a pointer to it as the | |
294 * !!! FIXME: audio callback's argument. This will clean up the | |
295 * !!! FIXME: namespace and let me reinitialize this for each file in | |
296 * !!! FIXME: a cleaner way. | |
297 */ | |
275 static Uint8 *decoded_ptr = NULL; | 298 static Uint8 *decoded_ptr = NULL; |
276 static Uint32 decoded_bytes = 0; | 299 static Uint32 decoded_bytes = 0; |
277 static int predecode = 0; | 300 static int predecode = 0; |
278 static int looping = 0; | 301 static int looping = 0; |
279 static int wants_volume_change = 0; | 302 static int wants_volume_change = 0; |
280 static float volume = 1.0; | 303 static float volume = 1.0; |
281 | 304 |
305 | |
282 /* | 306 /* |
283 * This updates (decoded_bytes) and (decoder_ptr) with more audio data, | 307 * This updates (decoded_bytes) and (decoder_ptr) with more audio data, |
284 * taking into account looping and/or predecoding. | 308 * taking into account looping and/or predecoding. |
285 */ | 309 */ |
286 static int read_more_data(Sound_Sample *sample) | 310 static int read_more_data(Sound_Sample *sample) |
307 | 331 |
308 /* No more to be read from stream, but we may want to loop the sample. */ | 332 /* No more to be read from stream, but we may want to loop the sample. */ |
309 | 333 |
310 if (!looping) | 334 if (!looping) |
311 return(0); | 335 return(0); |
336 | |
337 looping--; | |
312 | 338 |
313 /* we just need to point predecoded samples to the start of the buffer. */ | 339 /* we just need to point predecoded samples to the start of the buffer. */ |
314 if (predecode) | 340 if (predecode) |
315 { | 341 { |
316 decoded_bytes = sample->buffer_size; | 342 decoded_bytes = sample->buffer_size; |
395 *s16dst = SDL_SwapBE16(*s16dst); | 421 *s16dst = SDL_SwapBE16(*s16dst); |
396 } | 422 } |
397 break; | 423 break; |
398 } | 424 } |
399 } | 425 } |
426 | |
400 | 427 |
401 static void audio_callback(void *userdata, Uint8 *stream, int len) | 428 static void audio_callback(void *userdata, Uint8 *stream, int len) |
402 { | 429 { |
403 Sound_Sample *sample = (Sound_Sample *) userdata; | 430 Sound_Sample *sample = (Sound_Sample *) userdata; |
404 int bw = 0; /* bytes written to stream this time through the callback */ | 431 int bw = 0; /* bytes written to stream this time through the callback */ |
459 SDL_AudioSpec sdl_actual; | 486 SDL_AudioSpec sdl_actual; |
460 Sound_Sample *sample; | 487 Sound_Sample *sample; |
461 int use_specific_audiofmt = 0; | 488 int use_specific_audiofmt = 0; |
462 int i; | 489 int i; |
463 int delay; | 490 int delay; |
491 int new_sample = 1; | |
464 | 492 |
465 setbuf(stdout, NULL); | 493 setbuf(stdout, NULL); |
466 setbuf(stderr, NULL); | 494 setbuf(stderr, NULL); |
467 | 495 |
468 /* !!! FIXME: Move this to a parse_cmdline() function... */ | |
469 if (argc < 2) | 496 if (argc < 2) |
470 { | 497 { |
471 output_usage(argv[0]); | 498 output_usage(argv[0]); |
472 return(42); | 499 return(42); |
473 } /* if */ | 500 } /* if */ |
474 | 501 |
475 memset(&sound_desired, '\0', sizeof (sound_desired)); | 502 /* Check some command lines upfront. */ |
476 | |
477 for (i = 0; i < argc; i++) | 503 for (i = 0; i < argc; i++) |
478 { | 504 { |
479 if (strncmp(argv[i], "--", 2) != 0) | 505 if (strncmp(argv[i], "--", 2) != 0) |
480 continue; | 506 continue; |
481 | 507 |
494 else if (strcmp(argv[i], "--help") == 0) | 520 else if (strcmp(argv[i], "--help") == 0) |
495 { | 521 { |
496 output_usage(argv[0]); | 522 output_usage(argv[0]); |
497 return(42); | 523 return(42); |
498 } /* if */ | 524 } /* if */ |
499 | 525 |
500 else if (strcmp(argv[i], "--rate") == 0 && argc > i + 1) | 526 else if (strcmp(argv[i], "--decoders") == 0) |
527 { | |
528 if (!Sound_Init()) | |
529 { | |
530 fprintf(stderr, "Sound_Init() failed!\n" | |
531 " reason: [%s].\n", Sound_GetError()); | |
532 SDL_Quit(); | |
533 return(42); | |
534 } /* if */ | |
535 | |
536 output_decoders(); | |
537 Sound_Quit(); | |
538 return(0); | |
539 } /* else if */ | |
540 | |
541 /* !!! FIXME: Verify other --arguments are valid. */ | |
542 #if 0 | |
543 else | |
544 { | |
545 fprintf(stderr, "unknown option: \"%s\"\n", argv[i]); | |
546 return(42); | |
547 } /* else */ | |
548 #endif | |
549 } /* for */ | |
550 | |
551 if (!init_archive(argv[0])) | |
552 return(42); | |
553 | |
554 if (SDL_Init(SDL_INIT_AUDIO) == -1) | |
555 { | |
556 fprintf(stderr, "SDL_Init(SDL_INIT_AUDIO) failed!\n" | |
557 " reason: [%s].\n", SDL_GetError()); | |
558 return(42); | |
559 } /* if */ | |
560 | |
561 if (!Sound_Init()) | |
562 { | |
563 fprintf(stderr, "Sound_Init() failed!\n" | |
564 " reason: [%s].\n", Sound_GetError()); | |
565 SDL_Quit(); | |
566 return(42); | |
567 } /* if */ | |
568 | |
569 signal(SIGINT, sigint_catcher); | |
570 | |
571 for (i = 1; i < argc; i++) | |
572 { | |
573 char *filename = NULL; | |
574 | |
575 /* set variables back to defaults for next file... */ | |
576 if (new_sample) | |
577 { | |
578 new_sample = 0; | |
579 memset(&sound_desired, '\0', sizeof (sound_desired)); | |
580 done_flag = 0; | |
581 decoded_ptr = NULL; | |
582 decoded_bytes = 0; | |
583 predecode = 0; | |
584 looping = 0; | |
585 audio_buffersize = DEFAULT_AUDIOBUF; | |
586 decode_buffersize = DEFAULT_DECODEBUF; | |
587 sample = NULL; | |
588 use_specific_audiofmt = 0; | |
589 wants_volume_change = 0; | |
590 volume = 1.0; | |
591 } /* if */ | |
592 | |
593 if (strcmp(argv[i], "--rate") == 0 && argc > i + 1) | |
501 { | 594 { |
502 use_specific_audiofmt = 1; | 595 use_specific_audiofmt = 1; |
503 sound_desired.rate = atoi(argv[++i]); | 596 sound_desired.rate = atoi(argv[++i]); |
504 if (sound_desired.rate <= 0) | 597 if (sound_desired.rate <= 0) |
505 { | 598 { |
548 volume = atof(argv[++i]); | 641 volume = atof(argv[++i]); |
549 if (volume != 1.0) | 642 if (volume != 1.0) |
550 wants_volume_change = 1; | 643 wants_volume_change = 1; |
551 } /* else if */ | 644 } /* else if */ |
552 | 645 |
553 else if (strcmp(argv[i], "--decoders") == 0) | |
554 { | |
555 if (!Sound_Init()) | |
556 { | |
557 fprintf(stderr, "Sound_Init() failed!\n" | |
558 " reason: [%s].\n", Sound_GetError()); | |
559 SDL_Quit(); | |
560 return(42); | |
561 } /* if */ | |
562 | |
563 output_decoders(); | |
564 Sound_Quit(); | |
565 return(0); | |
566 } /* else if */ | |
567 | |
568 else if (strcmp(argv[i], "--predecode") == 0) | 646 else if (strcmp(argv[i], "--predecode") == 0) |
569 { | 647 { |
570 predecode = 1; | 648 predecode = 1; |
571 } /* else if */ | 649 } /* else if */ |
572 | 650 |
573 else if (strcmp(argv[i], "--loop") == 0) | 651 else if (strcmp(argv[i], "--loop") == 0) |
574 { | 652 { |
575 looping = 1; | 653 looping = atoi(argv[++i]); |
576 } /* else if */ | 654 } /* else if */ |
577 | 655 |
578 else if (strcmp(argv[i], "--stdin") == 0) | 656 else if (strcmp(argv[i], "--stdin") == 0) |
579 { | |
580 /* deal with it at Sound_Sample creation time... */ | |
581 } /* else if */ | |
582 | |
583 else | |
584 { | |
585 fprintf(stderr, "unknown option: \"%s\"\n", argv[i]); | |
586 return(42); | |
587 } /* else */ | |
588 } /* for */ | |
589 | |
590 /* Pick sensible defaults for any value not explicitly specified. */ | |
591 if (use_specific_audiofmt) | |
592 { | |
593 if (sound_desired.rate == 0) | |
594 sound_desired.rate = 44100; | |
595 if (sound_desired.format == 0) | |
596 sound_desired.format = AUDIO_S16SYS; | |
597 if (sound_desired.channels == 0) | |
598 sound_desired.channels = 2; | |
599 } /* if */ | |
600 | |
601 if (!init_archive(argv[0])) | |
602 return(42); | |
603 | |
604 if (SDL_Init(SDL_INIT_AUDIO) == -1) | |
605 { | |
606 fprintf(stderr, "SDL_Init(SDL_INIT_AUDIO) failed!\n" | |
607 " reason: [%s].\n", SDL_GetError()); | |
608 return(42); | |
609 } /* if */ | |
610 | |
611 if (!Sound_Init()) | |
612 { | |
613 fprintf(stderr, "Sound_Init() failed!\n" | |
614 " reason: [%s].\n", Sound_GetError()); | |
615 SDL_Quit(); | |
616 return(42); | |
617 } /* if */ | |
618 | |
619 signal(SIGINT, sigint_catcher); | |
620 | |
621 for (i = 1; i < argc; i++) | |
622 { | |
623 char *filename = NULL; | |
624 | |
625 /* !!! FIXME: This is ugly! */ | |
626 if ( (strcmp(argv[i], "--rate") == 0) || | |
627 (strcmp(argv[i], "--format") == 0) || | |
628 (strcmp(argv[i], "--channels") == 0) || | |
629 (strcmp(argv[i], "--audiobuf") == 0) || | |
630 (strcmp(argv[i], "--decodebuf") == 0) || | |
631 (strcmp(argv[i], "--volume") == 0) ) | |
632 { | |
633 i++; | |
634 continue; | |
635 } /* if */ | |
636 | |
637 if (strcmp(argv[i], "--stdin") == 0) | |
638 { | 657 { |
639 SDL_RWops *rw = SDL_RWFromFP(stdin, 1); | 658 SDL_RWops *rw = SDL_RWFromFP(stdin, 1); |
640 filename = "...from stdin..."; | 659 filename = "...from stdin..."; |
641 | 660 |
642 /* | 661 /* |
647 use_specific_audiofmt ? &sound_desired : NULL, | 666 use_specific_audiofmt ? &sound_desired : NULL, |
648 decode_buffersize); | 667 decode_buffersize); |
649 } /* if */ | 668 } /* if */ |
650 | 669 |
651 else if (strncmp(argv[i], "--", 2) == 0) | 670 else if (strncmp(argv[i], "--", 2) == 0) |
652 { | 671 /* ignore it. */ ; |
653 continue; | |
654 } /* else if */ | |
655 | 672 |
656 else | 673 else |
657 { | 674 { |
658 filename = argv[i]; | 675 filename = argv[i]; |
659 sample = sample_from_archive(filename, | 676 sample = sample_from_archive(filename, |
666 use_specific_audiofmt ? &sound_desired : NULL, | 683 use_specific_audiofmt ? &sound_desired : NULL, |
667 decode_buffersize); | 684 decode_buffersize); |
668 } /* if */ | 685 } /* if */ |
669 } /* else */ | 686 } /* else */ |
670 | 687 |
671 if (!sample) | 688 if (filename == NULL) /* still parsing command line stuff? */ |
689 continue; | |
690 | |
691 new_sample = 1; | |
692 | |
693 if (sample == NULL) | |
672 { | 694 { |
673 fprintf(stderr, "Couldn't load \"%s\"!\n" | 695 fprintf(stderr, "Couldn't load \"%s\"!\n" |
674 " reason: [%s].\n", filename, Sound_GetError()); | 696 " reason: [%s].\n", |
697 filename, Sound_GetError()); | |
675 continue; | 698 continue; |
676 } /* if */ | 699 } /* if */ |
677 | 700 |
678 /* | 701 /* |
679 * Unless explicitly specified, pick the format from the sound | 702 * Unless explicitly specified, pick the format from the sound |
680 * to be played. | 703 * to be played. |
681 */ | 704 */ |
682 if (use_specific_audiofmt) | 705 if (use_specific_audiofmt) |
683 { | 706 { |
707 /* Pick sensible default for any value not explicitly specified. */ | |
708 if (sound_desired.rate == 0) | |
709 sound_desired.rate = 44100; | |
710 if (sound_desired.format == 0) | |
711 sound_desired.format = AUDIO_S16SYS; | |
712 if (sound_desired.channels == 0) | |
713 sound_desired.channels = 2; | |
714 | |
684 sdl_desired.freq = sound_desired.rate; | 715 sdl_desired.freq = sound_desired.rate; |
685 sdl_desired.format = sound_desired.format; | 716 sdl_desired.format = sound_desired.format; |
686 sdl_desired.channels = sound_desired.channels; | 717 sdl_desired.channels = sound_desired.channels; |
687 } /* if */ | 718 } /* if */ |
688 else | 719 else |
724 { | 755 { |
725 printf("done.\n"); | 756 printf("done.\n"); |
726 } /* else */ | 757 } /* else */ |
727 } /* if */ | 758 } /* if */ |
728 | 759 |
729 done_flag = 0; | |
730 SDL_PauseAudio(0); | 760 SDL_PauseAudio(0); |
731 while (!done_flag) | 761 while (!done_flag) |
732 { | 762 { |
733 SDL_Delay(10); | 763 SDL_Delay(10); |
734 } /* while */ | 764 } /* while */ |