| /* _______ ____ __ ___ ___ |
| * \ _ \ \ / \ / \ \ / / ' ' ' |
| * | | \ \ | | || | \/ | . . |
| * | | | | | | || ||\ /| | |
| * | | | | | | || || \/ | | ' ' ' |
| * | | | | | | || || | | . . |
| * | |_/ / \ \__// || | | |
| * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque |
| * / \ |
| * / . \ |
| * dumbplay.c - Not-so-simple program to play / / \ \ |
| * music. It used to be simpler! | < / \_ |
| * | \/ /\ / |
| * By entheh. \_ / > / |
| * | \ / / |
| * IMPORTANT NOTE: This file is not very friendly. | ' / |
| * I strongly recommend AGAINST using it as a \__/ |
| * reference for writing your own code. If you would |
| * like to write a program that uses DUMB, or add DUMB to an existing |
| * project, please use docs/howto.txt. It will help you a lot more than this |
| * file can. (If you have difficulty reading documentation, you are lacking |
| * an important coding skill, and now is as good a time as any to learn.) |
| */ |
| |
| #include <stdlib.h> |
| #include <allegro.h> |
| |
| #ifndef ALLEGRO_DOS |
| #include <string.h> |
| #endif |
| |
| /* Note that your own programs should use <aldumb.h> not "aldumb.h". <> tells |
| * the compiler to look in the compiler's default header directory, which is |
| * where DUMB should be installed before you use it (make install does this). |
| * Use "" when it is your own header file. This example uses "" because DUMB |
| * might not have been installed yet when the makefile builds it. |
| */ |
| #include "aldumb.h" |
| |
| |
| |
| #ifndef ALLEGRO_DOS |
| static volatile int closed = 0; |
| static void closehook(void) { closed = 1; } |
| #else |
| #define closed 0 |
| #endif |
| |
| #ifdef ALLEGRO_WINDOWS |
| #define GFX_DUMB_MODE GFX_GDI |
| #include <winalleg.h> |
| #define YIELD() Sleep(1) |
| #else |
| #define GFX_DUMB_MODE GFX_AUTODETECT_WINDOWED |
| #ifdef ALLEGRO_UNIX |
| #include <sys/time.h> |
| static void YIELD(void) |
| { |
| struct timeval tv; |
| tv.tv_sec = 0; |
| tv.tv_usec = 1; |
| select(0, NULL, NULL, NULL, &tv); |
| } |
| #else |
| #define YIELD() yield_timeslice() |
| #endif |
| #endif |
| |
| |
| |
| #ifdef ALLEGRO_DOS |
| static int loop_callback(void *data) |
| { |
| (void)data; |
| printf("Music has looped.\n"); |
| return 0; |
| } |
| |
| static int xm_speed_zero_callback(void *data) |
| { |
| (void)data; |
| printf("Music has stopped.\n"); |
| return 0; |
| } |
| #else |
| static int gfx_half_width; |
| |
| static int loop_callback(void *data) |
| { |
| (void)data; |
| if (gfx_half_width) { |
| acquire_screen(); |
| textout_centre(screen, font, "Music has looped.", gfx_half_width, 36, 10); |
| release_screen(); |
| } |
| return 0; |
| } |
| |
| static int xm_speed_zero_callback(void *data) |
| { |
| (void)data; |
| if (gfx_half_width) { |
| text_mode(0); /* In case this is overwriting "Music has looped." */ |
| acquire_screen(); |
| textout_centre(screen, font, "Music has stopped.", gfx_half_width, 36, 10); |
| release_screen(); |
| } |
| return 0; |
| } |
| #endif |
| |
| |
| |
| static void usage(const char *exename) |
| { |
| allegro_message( |
| #ifdef ALLEGRO_WINDOWS |
| "Usage:\n" |
| " At the command line: %s file\n" |
| " In Windows Explorer: drag a file on to this program's icon.\n" |
| #else |
| "Usage: %s file\n" |
| #endif |
| "This will play the music file specified.\n" |
| "File formats supported: IT XM S3M MOD.\n" |
| "You can control playback quality by editing dumb.ini.\n", exename); |
| |
| exit(1); |
| } |
| |
| |
| |
| int main(int argc, const char *const *argv) /* I'm const-crazy! */ |
| { |
| DUH *duh; |
| AL_DUH_PLAYER *dp; |
| |
| if (allegro_init()) |
| return 1; |
| |
| if (argc != 2) |
| usage(argv[0]); |
| |
| set_config_file("dumb.ini"); |
| |
| if (install_keyboard()) { |
| allegro_message("Failed to initialise keyboard driver!\n"); |
| return 1; |
| } |
| |
| set_volume_per_voice(0); |
| |
| if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL)) { |
| allegro_message("Failed to initialise sound driver!\n%s\n", allegro_error); |
| return 1; |
| } |
| |
| atexit(&dumb_exit); |
| |
| dumb_register_packfiles(); |
| |
| duh = dumb_load_it(argv[1]); |
| if (!duh) { |
| duh = dumb_load_xm(argv[1]); |
| if (!duh) { |
| duh = dumb_load_s3m(argv[1]); |
| if (!duh) { |
| duh = dumb_load_mod(argv[1]); |
| if (!duh) { |
| allegro_message("Failed to load %s!\n", argv[1]); |
| return 1; |
| } |
| } |
| } |
| } |
| |
| dumb_resampling_quality = get_config_int("sound", "dumb_resampling_quality", 4); |
| dumb_it_max_to_mix = get_config_int("sound", "dumb_it_max_to_mix", 128); |
| |
| #ifndef ALLEGRO_DOS |
| { |
| const char *fn = get_filename(argv[1]); |
| gfx_half_width = strlen(fn); |
| if (gfx_half_width < 22) gfx_half_width = 22; |
| gfx_half_width = (gfx_half_width + 2) * 4; |
| |
| /* set_window_title() is not const-correct (yet). */ |
| set_window_title((char *)"DUMB Music Player"); |
| |
| if (set_gfx_mode(GFX_DUMB_MODE, gfx_half_width*2, 80, 0, 0) == 0) { |
| acquire_screen(); |
| textout_centre(screen, font, fn, gfx_half_width, 20, 14); |
| textout_centre(screen, font, "Press any key to exit.", gfx_half_width, 52, 11); |
| release_screen(); |
| } else |
| gfx_half_width = 0; |
| } |
| |
| #if ALLEGRO_VERSION*10000 + ALLEGRO_SUB_VERSION*100 + ALLEGRO_WIP_VERSION >= 40105 |
| set_close_button_callback(&closehook); |
| #else |
| set_window_close_hook(&closehook); |
| #endif |
| |
| #endif |
| |
| set_display_switch_mode(SWITCH_BACKGROUND); |
| |
| dp = al_start_duh(duh, 2, 0, 1.0f, |
| get_config_int("sound", "buffer_size", 4096), |
| get_config_int("sound", "sound_freq", 44100)); |
| |
| { |
| DUH_SIGRENDERER *sr = al_duh_get_sigrenderer(dp); |
| DUMB_IT_SIGRENDERER *itsr = duh_get_it_sigrenderer(sr); |
| dumb_it_set_loop_callback(itsr, &loop_callback, NULL); |
| dumb_it_set_xm_speed_zero_callback(itsr, &xm_speed_zero_callback, NULL); |
| } |
| |
| for (;;) { |
| if (keypressed()) { |
| readkey(); |
| break; |
| } |
| |
| if (al_poll_duh(dp) || closed) |
| break; |
| |
| YIELD(); |
| } |
| |
| al_stop_duh(dp); |
| |
| unload_duh(duh); |
| |
| return 0; |
| } |
| END_OF_MAIN(); |