/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * ESD sound driver. * * By Michael Bukin. * * Bug fixes by Peter Wang and Eduard Bloch. * * See readme.txt for copyright information. */ #include "allegro.h" #if (defined ALLEGRO_WITH_ESDDIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE)) #include "allegro/internal/aintern.h" #include "allegro/platform/aintunix.h" #include #include #include #include static int _al_esd_fd; static int _al_esd_bufsize; static unsigned char *_al_esd_bufdata; static int _al_esd_bits, _al_esd_signed, _al_esd_rate, _al_esd_stereo; static esd_format_t _al_esd_format; static int _al_esd_detect(int input); static int _al_esd_init(int input, int voices); static void _al_esd_exit(int input); static int _al_esd_mixer_volume(int volume); static int _al_esd_buffer_size(void); static char _al_esd_desc[256] = EMPTY_STRING; DIGI_DRIVER digi_esd = { DIGI_ESD, empty_string, empty_string, "Enlightened Sound Daemon", 0, 0, MIXER_MAX_SFX, MIXER_DEF_SFX, _al_esd_detect, _al_esd_init, _al_esd_exit, _al_esd_mixer_volume, NULL, NULL, _al_esd_buffer_size, _mixer_init_voice, _mixer_release_voice, _mixer_start_voice, _mixer_stop_voice, _mixer_loop_voice, _mixer_get_position, _mixer_set_position, _mixer_get_volume, _mixer_set_volume, _mixer_ramp_volume, _mixer_stop_volume_ramp, _mixer_get_frequency, _mixer_set_frequency, _mixer_sweep_frequency, _mixer_stop_frequency_sweep, _mixer_get_pan, _mixer_set_pan, _mixer_sweep_pan, _mixer_stop_pan_sweep, _mixer_set_echo, _mixer_set_tremolo, _mixer_set_vibrato, 0, 0, 0, 0, 0, 0, 0, 0 }; /* _al_esd_buffer_size: * Returns the current DMA buffer size, for use by the audiostream code. */ static int _al_esd_buffer_size(void) { return _al_esd_bufsize / (_al_esd_bits / 8) / (_al_esd_stereo ? 2 : 1); } /* _al_esd_update: * Update data. */ static void _al_esd_update(int threaded) { fd_set wfds; struct timeval timeout; FD_ZERO(&wfds); FD_SET(_al_esd_fd, &wfds); timeout.tv_sec = 0; timeout.tv_usec = 0; if (select(_al_esd_fd+1, NULL, &wfds, NULL, &timeout) > 0) { write(_al_esd_fd, _al_esd_bufdata, _al_esd_bufsize); _mix_some_samples((uintptr_t) _al_esd_bufdata, 0, _al_esd_signed); } } /* _al_esd_detect: * Detect driver presence. */ static int _al_esd_detect(int input) { int fd; AL_CONST char *server; char tmp1[128], tmp2[128], tmp3[16]; char s[256]; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return FALSE; } /* We don't want esdlib to spawn ESD while we are detecting it. */ putenv("ESD_NO_SPAWN=1"); /* Get ESD server name. */ server = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("esd_server", tmp2), uconvert_ascii("", tmp3)); /* Try to open ESD server. */ fd = esd_open_sound(uconvert_toascii(server, s)); if (fd < 0) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s: can not open"), (ugetc(server) ? server : get_config_text("No server"))); return FALSE; } esd_close(fd); return TRUE; } /* _al_esd_init: * ESD init routine. */ static int _al_esd_init(int input, int voices) { AL_CONST char *server; char tmp1[128], tmp2[128], tmp3[16]; char s[256]; if (input) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported")); return -1; } server = get_config_string(uconvert_ascii("sound", tmp1), uconvert_ascii("esd_server", tmp2), uconvert_ascii("", tmp3)); _al_esd_bits = (_sound_bits == 8) ? 8 : 16; _al_esd_stereo = (_sound_stereo) ? 1 : 0; _al_esd_rate = (_sound_freq > 0) ? _sound_freq : ESD_DEFAULT_RATE; _al_esd_signed = 1; _al_esd_format = (((_al_esd_bits == 16) ? ESD_BITS16 : ESD_BITS8) | (_al_esd_stereo ? ESD_STEREO : ESD_MONO) | ESD_STREAM | ESD_PLAY); _al_esd_fd = esd_play_stream_fallback(_al_esd_format, _al_esd_rate, uconvert_toascii(server, s), NULL); if (_al_esd_fd < 0) { uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s: can not open"), (ugetc(server) ? server : get_config_text("No server"))); return -1; } _al_esd_bufsize = ESD_BUF_SIZE; _al_esd_bufdata = malloc(_al_esd_bufsize); if (_al_esd_bufdata == 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer")); close(_al_esd_fd); return -1; } digi_esd.voices = voices; if (_mixer_init(_al_esd_bufsize / (_al_esd_bits / 8), _al_esd_rate, _al_esd_stereo, ((_al_esd_bits == 16) ? 1 : 0), &digi_esd.voices) != 0) { ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer")); free(_al_esd_bufdata); _al_esd_bufdata = 0; close(_al_esd_fd); return -1; } _mix_some_samples((uintptr_t) _al_esd_bufdata, 0, _al_esd_signed); /* Add audio interrupt. */ _unix_bg_man->register_func(_al_esd_update); uszprintf(_al_esd_desc, sizeof(_al_esd_desc), get_config_text("%s: %d bits, %s, %d bps, %s"), server, _al_esd_bits, uconvert_ascii((_al_esd_signed ? "signed" : "unsigned"), tmp1), _al_esd_rate, uconvert_ascii((_al_esd_stereo ? "stereo" : "mono"), tmp2)); digi_driver->desc = _al_esd_desc; return 0; } /* _al_esd_exit: * Shutdown ESD driver. */ static void _al_esd_exit(int input) { if (input) { return; } _unix_bg_man->unregister_func(_al_esd_update); free(_al_esd_bufdata); _al_esd_bufdata = 0; _mixer_exit(); close(_al_esd_fd); } /* _al_esd_mixer_volume: * Set mixer volume. */ static int _al_esd_mixer_volume(int volume) { return 0; } #ifdef ALLEGRO_MODULE /* _module_init: * Called when loaded as a dynamically linked module. */ void _module_init(int system_driver) { _unix_register_digi_driver(DIGI_ESD, &digi_esd, TRUE, TRUE); } #endif #endif