mirror of
https://github.com/aseprite/aseprite.git
synced 2024-10-06 06:50:07 +00:00
Remove sound/digi/midi/sample related stuff from Allegro code.
This commit is contained in:
parent
1b4ce4cf9b
commit
f9aa176c09
@ -9,7 +9,6 @@ set(ALLEGRO_SRC_FILES
|
||||
src/config.c
|
||||
src/datafile.c
|
||||
src/dataregi.c
|
||||
src/digmid.c
|
||||
src/dither.c
|
||||
src/dispsw.c
|
||||
src/drvlist.c
|
||||
@ -33,8 +32,6 @@ set(ALLEGRO_SRC_FILES
|
||||
src/lzss.c
|
||||
src/math.c
|
||||
src/math3d.c
|
||||
src/midi.c
|
||||
src/mixer.c
|
||||
src/mouse.c
|
||||
src/pcx.c
|
||||
src/poly3d.c
|
||||
@ -43,14 +40,11 @@ set(ALLEGRO_SRC_FILES
|
||||
src/quat.c
|
||||
src/readbmp.c
|
||||
src/readfont.c
|
||||
src/readsmp.c
|
||||
src/rle.c
|
||||
src/rotate.c
|
||||
src/rsfb.c
|
||||
src/scene3d.c
|
||||
src/sound.c
|
||||
src/spline.c
|
||||
src/stream.c
|
||||
src/text.c
|
||||
src/tga.c
|
||||
src/timer.c
|
||||
@ -107,10 +101,6 @@ set(ALLEGRO_SRC_WIN_FILES
|
||||
src/win/wddmode.c
|
||||
src/win/wddovl.c
|
||||
src/win/wddwin.c
|
||||
src/win/wdsinput.c
|
||||
src/win/wdsndmix.c
|
||||
src/win/wdsound.c
|
||||
src/win/wsndwo.c
|
||||
src/win/wdxver.c
|
||||
src/win/wdispsw.c
|
||||
src/win/wfile.c
|
||||
@ -118,9 +108,7 @@ set(ALLEGRO_SRC_WIN_FILES
|
||||
src/win/wgfxdrv.c
|
||||
src/win/winput.c
|
||||
src/win/wkeybd.c
|
||||
src/win/wmidi.c
|
||||
src/win/wmouse.c
|
||||
src/win/wsnddrv.c
|
||||
src/win/wsystem.c
|
||||
src/win/wthread.c
|
||||
src/win/wtimer.c
|
||||
@ -153,26 +141,17 @@ set(ALLEGRO_SRC_LINUX_FILES
|
||||
)
|
||||
|
||||
set(ALLEGRO_SRC_UNIX_FILES
|
||||
src/unix/alsa9.c
|
||||
src/unix/alsamidi.c
|
||||
src/unix/arts.c
|
||||
src/unix/sgial.c
|
||||
src/unix/jack.c
|
||||
src/unix/udjgpp.c
|
||||
src/unix/udrvlist.c
|
||||
src/unix/udummy.c
|
||||
src/unix/uesd.c
|
||||
src/unix/ufile.c
|
||||
src/unix/ugfxdrv.c
|
||||
src/unix/ukeybd.c
|
||||
src/unix/umain.c
|
||||
src/unix/umodules.c
|
||||
src/unix/umouse.c
|
||||
src/unix/uoss.c
|
||||
src/unix/uossmidi.c
|
||||
src/unix/uptimer.c
|
||||
src/unix/usigalrm.c
|
||||
src/unix/usnddrv.c
|
||||
src/unix/ustimer.c
|
||||
src/unix/usystem.c
|
||||
src/unix/uthreads.c
|
||||
@ -192,18 +171,14 @@ set(ALLEGRO_SRC_X_FILES
|
||||
)
|
||||
|
||||
set(ALLEGRO_SRC_MACOSX_FILES
|
||||
src/macosx/cadigi.m
|
||||
src/macosx/camidi.m
|
||||
src/macosx/drivers.m
|
||||
src/macosx/hidman.m
|
||||
src/macosx/keybd.m
|
||||
src/macosx/pcpu.m
|
||||
src/macosx/qtmidi.m
|
||||
src/macosx/quartz.m
|
||||
src/macosx/qzfull.m
|
||||
src/macosx/qzmouse.m
|
||||
src/macosx/qzwindow.m
|
||||
src/macosx/soundman.m
|
||||
src/macosx/system.m
|
||||
src/unix/ufile.c
|
||||
src/unix/utimer.c
|
||||
@ -224,7 +199,6 @@ set(ALLEGRO_INCLUDE_ALLEGRO_FILES
|
||||
include/allegro/config.h
|
||||
include/allegro/datafile.h
|
||||
include/allegro/debug.h
|
||||
include/allegro/digi.h
|
||||
include/allegro/draw.h
|
||||
include/allegro/file.h
|
||||
include/allegro/fix.h
|
||||
@ -237,13 +211,10 @@ set(ALLEGRO_INCLUDE_ALLEGRO_FILES
|
||||
include/allegro/keyboard.h
|
||||
include/allegro/lzss.h
|
||||
include/allegro/matrix.h
|
||||
include/allegro/midi.h
|
||||
include/allegro/mouse.h
|
||||
include/allegro/palette.h
|
||||
include/allegro/quat.h
|
||||
include/allegro/rle.h
|
||||
include/allegro/sound.h
|
||||
include/allegro/stream.h
|
||||
include/allegro/system.h
|
||||
include/allegro/text.h
|
||||
include/allegro/timer.h
|
||||
|
@ -45,8 +45,6 @@
|
||||
#include "allegro/fli.h"
|
||||
#include "allegro/config.h"
|
||||
|
||||
#include "allegro/sound.h"
|
||||
|
||||
#include "allegro/file.h"
|
||||
#include "allegro/lzss.h"
|
||||
#include "allegro/datafile.h"
|
||||
|
@ -35,8 +35,6 @@ struct RGB;
|
||||
#define DAT_FILE DAT_ID('F','I','L','E')
|
||||
#define DAT_DATA DAT_ID('D','A','T','A')
|
||||
#define DAT_FONT DAT_ID('F','O','N','T')
|
||||
#define DAT_SAMPLE DAT_ID('S','A','M','P')
|
||||
#define DAT_MIDI DAT_ID('M','I','D','I')
|
||||
#define DAT_PATCH DAT_ID('P','A','T',' ')
|
||||
#define DAT_FLI DAT_ID('F','L','I','C')
|
||||
#define DAT_BITMAP DAT_ID('B','M','P',' ')
|
||||
|
@ -1,219 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* Digital sound routines.
|
||||
*
|
||||
* By Shawn Hargreaves.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ALLEGRO_DIGI_H
|
||||
#define ALLEGRO_DIGI_H
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct PACKFILE;
|
||||
|
||||
|
||||
#define DIGI_VOICES 64 /* Theoretical maximums: */
|
||||
/* actual drivers may not be */
|
||||
/* able to handle this many */
|
||||
|
||||
typedef struct SAMPLE /* a sample */
|
||||
{
|
||||
int bits; /* 8 or 16 */
|
||||
int stereo; /* sample type flag */
|
||||
int freq; /* sample frequency */
|
||||
int priority; /* 0-255 */
|
||||
unsigned long len; /* length (in samples) */
|
||||
unsigned long loop_start; /* loop start position */
|
||||
unsigned long loop_end; /* loop finish position */
|
||||
unsigned long param; /* for internal use by the driver */
|
||||
void *data; /* sample data */
|
||||
} SAMPLE;
|
||||
|
||||
|
||||
#define DIGI_AUTODETECT -1 /* for passing to install_sound() */
|
||||
#define DIGI_NONE 0
|
||||
|
||||
typedef struct DIGI_DRIVER /* driver for playing digital sfx */
|
||||
{
|
||||
int id; /* driver ID code */
|
||||
AL_CONST char *name; /* driver name */
|
||||
AL_CONST char *desc; /* description string */
|
||||
AL_CONST char *ascii_name; /* ASCII format name string */
|
||||
int voices; /* available voices */
|
||||
int basevoice; /* voice number offset */
|
||||
int max_voices; /* maximum voices we can support */
|
||||
int def_voices; /* default number of voices to use */
|
||||
|
||||
/* setup routines */
|
||||
AL_METHOD(int, detect, (int input));
|
||||
AL_METHOD(int, init, (int input, int voices));
|
||||
AL_METHOD(void, exit, (int input));
|
||||
AL_METHOD(int, set_mixer_volume, (int volume));
|
||||
AL_METHOD(int, get_mixer_volume, (void));
|
||||
|
||||
/* for use by the audiostream functions */
|
||||
AL_METHOD(void *, lock_voice, (int voice, int start, int end));
|
||||
AL_METHOD(void, unlock_voice, (int voice));
|
||||
AL_METHOD(int, buffer_size, (void));
|
||||
|
||||
/* voice control functions */
|
||||
AL_METHOD(void, init_voice, (int voice, AL_CONST SAMPLE *sample));
|
||||
AL_METHOD(void, release_voice, (int voice));
|
||||
AL_METHOD(void, start_voice, (int voice));
|
||||
AL_METHOD(void, stop_voice, (int voice));
|
||||
AL_METHOD(void, loop_voice, (int voice, int playmode));
|
||||
|
||||
/* position control functions */
|
||||
AL_METHOD(int, get_position, (int voice));
|
||||
AL_METHOD(void, set_position, (int voice, int position));
|
||||
|
||||
/* volume control functions */
|
||||
AL_METHOD(int, get_volume, (int voice));
|
||||
AL_METHOD(void, set_volume, (int voice, int volume));
|
||||
AL_METHOD(void, ramp_volume, (int voice, int tyme, int endvol));
|
||||
AL_METHOD(void, stop_volume_ramp, (int voice));
|
||||
|
||||
/* pitch control functions */
|
||||
AL_METHOD(int, get_frequency, (int voice));
|
||||
AL_METHOD(void, set_frequency, (int voice, int frequency));
|
||||
AL_METHOD(void, sweep_frequency, (int voice, int tyme, int endfreq));
|
||||
AL_METHOD(void, stop_frequency_sweep, (int voice));
|
||||
|
||||
/* pan control functions */
|
||||
AL_METHOD(int, get_pan, (int voice));
|
||||
AL_METHOD(void, set_pan, (int voice, int pan));
|
||||
AL_METHOD(void, sweep_pan, (int voice, int tyme, int endpan));
|
||||
AL_METHOD(void, stop_pan_sweep, (int voice));
|
||||
|
||||
/* effect control functions */
|
||||
AL_METHOD(void, set_echo, (int voice, int strength, int delay));
|
||||
AL_METHOD(void, set_tremolo, (int voice, int rate, int depth));
|
||||
AL_METHOD(void, set_vibrato, (int voice, int rate, int depth));
|
||||
|
||||
/* input functions */
|
||||
int rec_cap_bits;
|
||||
int rec_cap_stereo;
|
||||
AL_METHOD(int, rec_cap_rate, (int bits, int stereo));
|
||||
AL_METHOD(int, rec_cap_parm, (int rate, int bits, int stereo));
|
||||
AL_METHOD(int, rec_source, (int source));
|
||||
AL_METHOD(int, rec_start, (int rate, int bits, int stereo));
|
||||
AL_METHOD(void, rec_stop, (void));
|
||||
AL_METHOD(int, rec_read, (void *buf));
|
||||
} DIGI_DRIVER;
|
||||
|
||||
AL_ARRAY(_DRIVER_INFO, _digi_driver_list);
|
||||
|
||||
/* macros for constructing the driver lists */
|
||||
#define BEGIN_DIGI_DRIVER_LIST \
|
||||
_DRIVER_INFO _digi_driver_list[] = \
|
||||
{
|
||||
|
||||
#define END_DIGI_DRIVER_LIST \
|
||||
{ 0, NULL, 0 } \
|
||||
};
|
||||
|
||||
AL_VAR(DIGI_DRIVER *, digi_driver);
|
||||
|
||||
AL_VAR(DIGI_DRIVER *, digi_input_driver);
|
||||
|
||||
AL_VAR(int, digi_card);
|
||||
|
||||
AL_VAR(int, digi_input_card);
|
||||
|
||||
AL_FUNC(int, detect_digi_driver, (int driver_id));
|
||||
|
||||
|
||||
AL_FUNC(SAMPLE *, load_sample, (AL_CONST char *filename));
|
||||
AL_FUNC(SAMPLE *, load_wav, (AL_CONST char *filename));
|
||||
AL_FUNC(SAMPLE *, load_wav_pf, (struct PACKFILE *f));
|
||||
AL_FUNC(SAMPLE *, load_voc, (AL_CONST char *filename));
|
||||
AL_FUNC(SAMPLE *, load_voc_pf, (struct PACKFILE *f));
|
||||
AL_FUNC(int, save_sample, (AL_CONST char *filename, SAMPLE *spl));
|
||||
AL_FUNC(SAMPLE *, create_sample, (int bits, int stereo, int freq, int len));
|
||||
AL_FUNC(void, destroy_sample, (SAMPLE *spl));
|
||||
|
||||
AL_FUNC(int, play_sample, (AL_CONST SAMPLE *spl, int vol, int pan, int freq, int loop));
|
||||
AL_FUNC(void, stop_sample, (AL_CONST SAMPLE *spl));
|
||||
AL_FUNC(void, adjust_sample, (AL_CONST SAMPLE *spl, int vol, int pan, int freq, int loop));
|
||||
|
||||
AL_FUNC(int, allocate_voice, (AL_CONST SAMPLE *spl));
|
||||
AL_FUNC(void, deallocate_voice, (int voice));
|
||||
AL_FUNC(void, reallocate_voice, (int voice, AL_CONST SAMPLE *spl));
|
||||
AL_FUNC(void, release_voice, (int voice));
|
||||
AL_FUNC(void, voice_start, (int voice));
|
||||
AL_FUNC(void, voice_stop, (int voice));
|
||||
AL_FUNC(void, voice_set_priority, (int voice, int priority));
|
||||
AL_FUNC(SAMPLE *, voice_check, (int voice));
|
||||
|
||||
#define PLAYMODE_PLAY 0
|
||||
#define PLAYMODE_LOOP 1
|
||||
#define PLAYMODE_FORWARD 0
|
||||
#define PLAYMODE_BACKWARD 2
|
||||
#define PLAYMODE_BIDIR 4
|
||||
|
||||
AL_FUNC(void, voice_set_playmode, (int voice, int playmode));
|
||||
|
||||
AL_FUNC(int, voice_get_position, (int voice));
|
||||
AL_FUNC(void, voice_set_position, (int voice, int position));
|
||||
|
||||
AL_FUNC(int, voice_get_volume, (int voice));
|
||||
AL_FUNC(void, voice_set_volume, (int voice, int volume));
|
||||
AL_FUNC(void, voice_ramp_volume, (int voice, int tyme, int endvol));
|
||||
AL_FUNC(void, voice_stop_volumeramp, (int voice));
|
||||
|
||||
AL_FUNC(int, voice_get_frequency, (int voice));
|
||||
AL_FUNC(void, voice_set_frequency, (int voice, int frequency));
|
||||
AL_FUNC(void, voice_sweep_frequency, (int voice, int tyme, int endfreq));
|
||||
AL_FUNC(void, voice_stop_frequency_sweep, (int voice));
|
||||
|
||||
AL_FUNC(int, voice_get_pan, (int voice));
|
||||
AL_FUNC(void, voice_set_pan, (int voice, int pan));
|
||||
AL_FUNC(void, voice_sweep_pan, (int voice, int tyme, int endpan));
|
||||
AL_FUNC(void, voice_stop_pan_sweep, (int voice));
|
||||
|
||||
AL_FUNC(void, voice_set_echo, (int voice, int strength, int delay));
|
||||
AL_FUNC(void, voice_set_tremolo, (int voice, int rate, int depth));
|
||||
AL_FUNC(void, voice_set_vibrato, (int voice, int rate, int depth));
|
||||
|
||||
#define SOUND_INPUT_MIC 1
|
||||
#define SOUND_INPUT_LINE 2
|
||||
#define SOUND_INPUT_CD 3
|
||||
|
||||
AL_FUNC(int, get_sound_input_cap_bits, (void));
|
||||
AL_FUNC(int, get_sound_input_cap_stereo, (void));
|
||||
AL_FUNC(int, get_sound_input_cap_rate, (int bits, int stereo));
|
||||
AL_FUNC(int, get_sound_input_cap_parm, (int rate, int bits, int stereo));
|
||||
AL_FUNC(int, set_sound_input_source, (int source));
|
||||
AL_FUNC(int, start_sound_input, (int rate, int bits, int stereo));
|
||||
AL_FUNC(void, stop_sound_input, (void));
|
||||
AL_FUNC(int, read_sound_input, (void *buffer));
|
||||
|
||||
AL_FUNCPTR(void, digi_recorder, (void));
|
||||
|
||||
AL_FUNC(void, lock_sample, (struct SAMPLE *spl));
|
||||
|
||||
AL_FUNC(void, register_sample_file_type, (AL_CONST char *ext, AL_METHOD(struct SAMPLE *, load, (AL_CONST char *filename)), AL_METHOD(int, save, (AL_CONST char *filename, struct SAMPLE *spl))));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ifndef ALLEGRO_DIGI_H */
|
||||
|
||||
|
@ -1005,96 +1005,6 @@ AL_FUNC(void, _poly_zbuf_ptex_mask_trans32, (uintptr_t addr, int w, POLYGON_SEGM
|
||||
#endif
|
||||
|
||||
|
||||
/* sound lib stuff */
|
||||
AL_VAR(MIDI_DRIVER, _midi_none);
|
||||
AL_VAR(int, _digi_volume);
|
||||
AL_VAR(int, _midi_volume);
|
||||
AL_VAR(int, _sound_flip_pan);
|
||||
AL_VAR(int, _sound_hq);
|
||||
AL_VAR(int, _sound_stereo);
|
||||
AL_VAR(int, _sound_bits);
|
||||
AL_VAR(int, _sound_freq);
|
||||
AL_VAR(int, _sound_port);
|
||||
AL_VAR(int, _sound_dma);
|
||||
AL_VAR(int, _sound_irq);
|
||||
|
||||
AL_VAR(int, _sound_installed);
|
||||
AL_VAR(int, _sound_input_installed);
|
||||
|
||||
AL_FUNC(int, _midi_allocate_voice, (int min, int max));
|
||||
|
||||
AL_VAR(volatile long, _midi_tick);
|
||||
|
||||
AL_FUNC(int, _digmid_find_patches, (char *dir, int dir_size, char *file, int size_of_file));
|
||||
|
||||
#define VIRTUAL_VOICES 256
|
||||
|
||||
|
||||
typedef struct /* a virtual (as seen by the user) soundcard voice */
|
||||
{
|
||||
AL_CONST SAMPLE *sample; /* which sample are we playing? (NULL = free) */
|
||||
int num; /* physical voice number (-1 = been killed off) */
|
||||
int autokill; /* set to free the voice when the sample finishes */
|
||||
long time; /* when we were started (for voice allocation) */
|
||||
int priority; /* how important are we? */
|
||||
} VOICE;
|
||||
|
||||
|
||||
typedef struct /* a physical (as used by hardware) soundcard voice */
|
||||
{
|
||||
int num; /* the virtual voice currently using me (-1 = free) */
|
||||
int playmode; /* are we looping? */
|
||||
int vol; /* current volume (fixed point .12) */
|
||||
int dvol; /* volume delta, for ramping */
|
||||
int target_vol; /* target volume, for ramping */
|
||||
int pan; /* current pan (fixed point .12) */
|
||||
int dpan; /* pan delta, for sweeps */
|
||||
int target_pan; /* target pan, for sweeps */
|
||||
int freq; /* current frequency (fixed point .12) */
|
||||
int dfreq; /* frequency delta, for sweeps */
|
||||
int target_freq; /* target frequency, for sweeps */
|
||||
} PHYS_VOICE;
|
||||
|
||||
AL_ARRAY(PHYS_VOICE, _phys_voice);
|
||||
|
||||
|
||||
#define MIXER_DEF_SFX 8
|
||||
#define MIXER_MAX_SFX 64
|
||||
|
||||
AL_FUNC(int, _mixer_init, (int bufsize, int freq, int stereo, int is16bit, int *voices));
|
||||
AL_FUNC(void, _mixer_exit, (void));
|
||||
AL_FUNC(void, _mix_some_samples, (uintptr_t buf, unsigned short seg, int issigned));
|
||||
AL_FUNC(void, _mixer_init_voice, (int voice, AL_CONST SAMPLE *sample));
|
||||
AL_FUNC(void, _mixer_release_voice, (int voice));
|
||||
AL_FUNC(void, _mixer_start_voice, (int voice));
|
||||
AL_FUNC(void, _mixer_stop_voice, (int voice));
|
||||
AL_FUNC(void, _mixer_loop_voice, (int voice, int loopmode));
|
||||
AL_FUNC(int, _mixer_get_position, (int voice));
|
||||
AL_FUNC(void, _mixer_set_position, (int voice, int position));
|
||||
AL_FUNC(int, _mixer_get_volume, (int voice));
|
||||
AL_FUNC(void, _mixer_set_volume, (int voice, int volume));
|
||||
AL_FUNC(void, _mixer_ramp_volume, (int voice, int tyme, int endvol));
|
||||
AL_FUNC(void, _mixer_stop_volume_ramp, (int voice));
|
||||
AL_FUNC(int, _mixer_get_frequency, (int voice));
|
||||
AL_FUNC(void, _mixer_set_frequency, (int voice, int frequency));
|
||||
AL_FUNC(void, _mixer_sweep_frequency, (int voice, int tyme, int endfreq));
|
||||
AL_FUNC(void, _mixer_stop_frequency_sweep, (int voice));
|
||||
AL_FUNC(int, _mixer_get_pan, (int voice));
|
||||
AL_FUNC(void, _mixer_set_pan, (int voice, int pan));
|
||||
AL_FUNC(void, _mixer_sweep_pan, (int voice, int tyme, int endpan));
|
||||
AL_FUNC(void, _mixer_stop_pan_sweep, (int voice));
|
||||
AL_FUNC(void, _mixer_set_echo, (int voice, int strength, int delay));
|
||||
AL_FUNC(void, _mixer_set_tremolo, (int voice, int rate, int depth));
|
||||
AL_FUNC(void, _mixer_set_vibrato, (int voice, int rate, int depth));
|
||||
|
||||
AL_FUNC(void, _dummy_noop1, (int p));
|
||||
AL_FUNC(void, _dummy_noop2, (int p1, int p2));
|
||||
AL_FUNC(void, _dummy_noop3, (int p1, int p2, int p3));
|
||||
AL_FUNC(int, _dummy_load_patches, (AL_CONST char *patches, AL_CONST char *drums));
|
||||
AL_FUNC(void, _dummy_adjust_patches, (AL_CONST char *patches, AL_CONST char *drums));
|
||||
AL_FUNC(void, _dummy_key_on, (int inst, int note, int bend, int vol, int pan));
|
||||
|
||||
|
||||
/* datafile ID's for compatibility with the old datafile format */
|
||||
#define V1_DAT_MAGIC 0x616C6C2EL
|
||||
|
||||
@ -1110,8 +1020,6 @@ AL_FUNC(void, _dummy_key_on, (int inst, int note, int bend, int vol, int pan));
|
||||
#define V1_DAT_FONT_PROP 9
|
||||
#define V1_DAT_BITMAP 10
|
||||
#define V1_DAT_PALETTE 11
|
||||
#define V1_DAT_SAMPLE 12
|
||||
#define V1_DAT_MIDI 13
|
||||
#define V1_DAT_RLE_SPRITE 14
|
||||
#define V1_DAT_FLI 15
|
||||
#define V1_DAT_C_SPRITE 16
|
||||
@ -1146,22 +1054,11 @@ AL_FUNC(void, _construct_datafile, (DATAFILE *data));
|
||||
/* for readbmp.c */
|
||||
AL_FUNC(void, _register_bitmap_file_type_init, (void));
|
||||
|
||||
/* for readsmp.c */
|
||||
AL_FUNC(void, _register_sample_file_type_init, (void));
|
||||
|
||||
/* for readfont.c */
|
||||
AL_FUNC(void, _register_font_file_type_init, (void));
|
||||
|
||||
|
||||
/* for module linking system; see comment in allegro.c */
|
||||
struct _AL_LINKER_MIDI
|
||||
{
|
||||
AL_METHOD(int, init, (void));
|
||||
AL_METHOD(void, exit, (void));
|
||||
};
|
||||
|
||||
AL_VAR(struct _AL_LINKER_MIDI *, _al_linker_midi);
|
||||
|
||||
struct _AL_LINKER_MOUSE
|
||||
{
|
||||
AL_METHOD(void, set_mouse_etc, (void));
|
||||
|
@ -1,144 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* MIDI music routines.
|
||||
*
|
||||
* By Shawn Hargreaves.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ALLEGRO_MIDI_H
|
||||
#define ALLEGRO_MIDI_H
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* Theoretical maximums: */
|
||||
#define MIDI_VOICES 64 /* actual drivers may not be */
|
||||
#define MIDI_TRACKS 32 /* able to handle this many */
|
||||
|
||||
|
||||
|
||||
typedef struct MIDI /* a midi file */
|
||||
{
|
||||
int divisions; /* number of ticks per quarter note */
|
||||
struct {
|
||||
unsigned char *data; /* MIDI message stream */
|
||||
int len; /* length of the track data */
|
||||
} track[MIDI_TRACKS];
|
||||
} MIDI;
|
||||
|
||||
|
||||
|
||||
#define MIDI_AUTODETECT -1
|
||||
#define MIDI_NONE 0
|
||||
#define MIDI_DIGMID AL_ID('D','I','G','I')
|
||||
|
||||
typedef struct MIDI_DRIVER /* driver for playing midi music */
|
||||
{
|
||||
int id; /* driver ID code */
|
||||
AL_CONST char *name; /* driver name */
|
||||
AL_CONST char *desc; /* description string */
|
||||
AL_CONST char *ascii_name; /* ASCII format name string */
|
||||
int voices; /* available voices */
|
||||
int basevoice; /* voice number offset */
|
||||
int max_voices; /* maximum voices we can support */
|
||||
int def_voices; /* default number of voices to use */
|
||||
int xmin, xmax; /* reserved voice range */
|
||||
|
||||
/* setup routines */
|
||||
AL_METHOD(int, detect, (int input));
|
||||
AL_METHOD(int, init, (int input, int voices));
|
||||
AL_METHOD(void, exit, (int input));
|
||||
AL_METHOD(int, set_mixer_volume, (int volume));
|
||||
AL_METHOD(int, get_mixer_volume, (void));
|
||||
|
||||
/* raw MIDI output to MPU-401, etc. */
|
||||
AL_METHOD(void, raw_midi, (int data));
|
||||
|
||||
/* dynamic patch loading routines */
|
||||
AL_METHOD(int, load_patches, (AL_CONST char *patches, AL_CONST char *drums));
|
||||
AL_METHOD(void, adjust_patches, (AL_CONST char *patches, AL_CONST char *drums));
|
||||
|
||||
/* note control functions */
|
||||
AL_METHOD(void, key_on, (int inst, int note, int bend, int vol, int pan));
|
||||
AL_METHOD(void, key_off, (int voice));
|
||||
AL_METHOD(void, set_volume, (int voice, int vol));
|
||||
AL_METHOD(void, set_pitch, (int voice, int note, int bend));
|
||||
AL_METHOD(void, set_pan, (int voice, int pan));
|
||||
AL_METHOD(void, set_vibrato, (int voice, int amount));
|
||||
} MIDI_DRIVER;
|
||||
|
||||
|
||||
AL_VAR(MIDI_DRIVER, midi_digmid);
|
||||
|
||||
AL_ARRAY(_DRIVER_INFO, _midi_driver_list);
|
||||
|
||||
|
||||
/* macros for constructing the driver lists */
|
||||
#define BEGIN_MIDI_DRIVER_LIST \
|
||||
_DRIVER_INFO _midi_driver_list[] = \
|
||||
{
|
||||
|
||||
#define END_MIDI_DRIVER_LIST \
|
||||
{ 0, NULL, 0 } \
|
||||
};
|
||||
|
||||
#define MIDI_DRIVER_DIGMID \
|
||||
{ MIDI_DIGMID, &midi_digmid, TRUE },
|
||||
|
||||
|
||||
AL_VAR(MIDI_DRIVER *, midi_driver);
|
||||
|
||||
AL_VAR(MIDI_DRIVER *, midi_input_driver);
|
||||
|
||||
AL_VAR(int, midi_card);
|
||||
|
||||
AL_VAR(int, midi_input_card);
|
||||
|
||||
AL_VAR(volatile long, midi_pos); /* current position in the midi file, in beats */
|
||||
AL_VAR(volatile long, midi_time); /* current position in the midi file, in seconds */
|
||||
|
||||
AL_VAR(long, midi_loop_start); /* where to loop back to at EOF */
|
||||
AL_VAR(long, midi_loop_end); /* loop when we hit this position */
|
||||
|
||||
AL_FUNC(int, detect_midi_driver, (int driver_id));
|
||||
|
||||
AL_FUNC(MIDI *, load_midi, (AL_CONST char *filename));
|
||||
AL_FUNC(void, destroy_midi, (MIDI *midi));
|
||||
AL_FUNC(int, play_midi, (MIDI *midi, int loop));
|
||||
AL_FUNC(int, play_looped_midi, (MIDI *midi, int loop_start, int loop_end));
|
||||
AL_FUNC(void, stop_midi, (void));
|
||||
AL_FUNC(void, midi_pause, (void));
|
||||
AL_FUNC(void, midi_resume, (void));
|
||||
AL_FUNC(int, midi_seek, (int target));
|
||||
AL_FUNC(int, get_midi_length, (MIDI *midi));
|
||||
AL_FUNC(void, midi_out, (unsigned char *data, int length));
|
||||
AL_FUNC(int, load_midi_patches, (void));
|
||||
|
||||
AL_FUNCPTR(void, midi_msg_callback, (int msg, int byte1, int byte2));
|
||||
AL_FUNCPTR(void, midi_meta_callback, (int type, AL_CONST unsigned char *data, int length));
|
||||
AL_FUNCPTR(void, midi_sysex_callback, (AL_CONST unsigned char *data, int length));
|
||||
|
||||
AL_FUNCPTR(void, midi_recorder, (unsigned char data));
|
||||
|
||||
AL_FUNC(void, lock_midi, (struct MIDI *midi));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ifndef ALLEGRO_MIDI_H */
|
||||
|
||||
|
@ -66,13 +66,9 @@ extern "C" {
|
||||
|
||||
/* Dynamic driver lists, for modules */
|
||||
AL_VAR(_DRIVER_INFO *, _unix_gfx_driver_list);
|
||||
AL_VAR(_DRIVER_INFO *, _unix_digi_driver_list);
|
||||
AL_VAR(_DRIVER_INFO *, _unix_midi_driver_list);
|
||||
AL_FUNC(void, _unix_driver_lists_init, (void));
|
||||
AL_FUNC(void, _unix_driver_lists_shutdown, (void));
|
||||
AL_FUNC(void, _unix_register_gfx_driver, (int id, GFX_DRIVER *driver, int autodetect, int priority));
|
||||
AL_FUNC(void, _unix_register_digi_driver, (int id, DIGI_DRIVER *driver, int autodetect, int priority));
|
||||
AL_FUNC(void, _unix_register_midi_driver, (int id, MIDI_DRIVER *driver, int autodetect, int priority));
|
||||
|
||||
/* Get size of a memory page in bytes */
|
||||
AL_FUNC(size_t, _unix_get_page_size, (void));
|
||||
@ -136,12 +132,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ALLEGRO_WITH_OSSDIGI
|
||||
/* So the setup program can read what we detected */
|
||||
AL_VAR(int, _oss_fragsize);
|
||||
AL_VAR(int, _oss_numfrags);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -146,32 +146,6 @@ AL_FUNC(void, sys_directx_lock_mutex, (void *handle));
|
||||
AL_FUNC(void, sys_directx_unlock_mutex, (void *handle));
|
||||
|
||||
|
||||
/* sound routines */
|
||||
AL_FUNC(_DRIVER_INFO *, _get_win_digi_driver_list, (void));
|
||||
AL_FUNC(void, _free_win_digi_driver_list, (void));
|
||||
|
||||
AL_FUNC(DIGI_DRIVER *, _get_dsalmix_driver, (char *name, LPGUID guid, int num));
|
||||
AL_FUNC(void, _free_win_dsalmix_name_list, (void));
|
||||
AL_FUNC(DIGI_DRIVER *, _get_woalmix_driver, (int num));
|
||||
|
||||
AL_FUNC(int, digi_directsound_capture_init, (LPGUID guid));
|
||||
AL_FUNC(void, digi_directsound_capture_exit, (void));
|
||||
AL_FUNC(int, digi_directsound_capture_detect, (LPGUID guid));
|
||||
AL_FUNC(int, digi_directsound_rec_cap_rate, (int bits, int stereo));
|
||||
AL_FUNC(int, digi_directsound_rec_cap_param, (int rate, int bits, int stereo));
|
||||
AL_FUNC(int, digi_directsound_rec_source, (int source));
|
||||
AL_FUNC(int, digi_directsound_rec_start, (int rate, int bits, int stereo));
|
||||
AL_FUNC(void, digi_directsound_rec_stop, (void));
|
||||
AL_FUNC(int, digi_directsound_rec_read, (void *buf));
|
||||
|
||||
|
||||
/* midi routines */
|
||||
AL_FUNC(_DRIVER_INFO *, _get_win_midi_driver_list, (void));
|
||||
AL_FUNC(void, _free_win_midi_driver_list, (void));
|
||||
|
||||
AL_FUNC(void, midi_switch_out, (void));
|
||||
|
||||
|
||||
/* file routines */
|
||||
AL_VAR(int, _al_win_unicode_filenames);
|
||||
|
||||
|
@ -95,17 +95,5 @@ AL_VAR(MOUSE_DRIVER, mouse_macosx);
|
||||
AL_VAR(GFX_DRIVER, gfx_quartz_window);
|
||||
AL_VAR(GFX_DRIVER, gfx_quartz_full);
|
||||
|
||||
/* Digital sound drivers */
|
||||
#define DIGI_CORE_AUDIO AL_ID('D','C','A',' ')
|
||||
#define DIGI_SOUND_MANAGER AL_ID('S','N','D','M')
|
||||
AL_VAR(DIGI_DRIVER, digi_core_audio);
|
||||
AL_VAR(DIGI_DRIVER, digi_sound_manager);
|
||||
|
||||
/* MIDI music drivers */
|
||||
#define MIDI_CORE_AUDIO AL_ID('M','C','A',' ')
|
||||
#define MIDI_QUICKTIME AL_ID('Q','T','M',' ')
|
||||
AL_VAR(MIDI_DRIVER, midi_core_audio);
|
||||
AL_VAR(MIDI_DRIVER, midi_quicktime);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -57,76 +57,6 @@ AL_VAR(TIMER_DRIVER, timerdrv_unix_sigalrm);
|
||||
|
||||
|
||||
|
||||
/************************************/
|
||||
/*********** Sound drivers **********/
|
||||
/************************************/
|
||||
|
||||
#define DIGI_OSS AL_ID('O','S','S','D')
|
||||
#define MIDI_OSS AL_ID('O','S','S','M')
|
||||
#define DIGI_ESD AL_ID('E','S','D','D')
|
||||
#define DIGI_ARTS AL_ID('A','R','T','S')
|
||||
#define DIGI_SGIAL AL_ID('S','G','I','A')
|
||||
#define DIGI_ALSA AL_ID('A','L','S','A')
|
||||
#define MIDI_ALSA AL_ID('A','M','I','D')
|
||||
#define DIGI_JACK AL_ID('J','A','C','K')
|
||||
|
||||
|
||||
#ifdef ALLEGRO_WITH_OSSDIGI
|
||||
AL_VAR(DIGI_DRIVER, digi_oss);
|
||||
#define DIGI_DRIVER_OSS \
|
||||
{ DIGI_OSS, &digi_oss, TRUE },
|
||||
#endif /* ALLEGRO_WITH_OSSDIGI */
|
||||
|
||||
#ifdef ALLEGRO_WITH_OSSMIDI
|
||||
AL_VAR(MIDI_DRIVER, midi_oss);
|
||||
#define MIDI_DRIVER_OSS \
|
||||
{ MIDI_OSS, &midi_oss, TRUE },
|
||||
#endif /* ALLEGRO_WITH_OSSMIDI */
|
||||
|
||||
#ifndef ALLEGRO_WITH_MODULES
|
||||
|
||||
#ifdef ALLEGRO_WITH_ESDDIGI
|
||||
AL_VAR(DIGI_DRIVER, digi_esd);
|
||||
#define DIGI_DRIVER_ESD \
|
||||
{ DIGI_ESD, &digi_esd, TRUE },
|
||||
#endif /* ALLEGRO_WITH_ESDDIGI */
|
||||
|
||||
#ifdef ALLEGRO_WITH_ARTSDIGI
|
||||
AL_VAR(DIGI_DRIVER, digi_arts);
|
||||
#define DIGI_DRIVER_ARTS \
|
||||
{ DIGI_ARTS, &digi_arts, TRUE },
|
||||
#endif /* ALLEGRO_WITH_ARTSDIGI */
|
||||
|
||||
#ifdef ALLEGRO_WITH_SGIALDIGI
|
||||
AL_VAR(DIGI_DRIVER, digi_sgial);
|
||||
#define DIGI_DRIVER_SGIAL \
|
||||
{ DIGI_SGIAL, &digi_sgial, TRUE },
|
||||
#endif /* ALLEGRO_WITH_SGIALDIGI */
|
||||
|
||||
#ifdef ALLEGRO_WITH_ALSADIGI
|
||||
AL_VAR(DIGI_DRIVER, digi_alsa);
|
||||
#define DIGI_DRIVER_ALSA \
|
||||
{ DIGI_ALSA, &digi_alsa, TRUE },
|
||||
#endif /* ALLEGRO_WITH_ALSADIGI */
|
||||
|
||||
|
||||
#ifdef ALLEGRO_WITH_ALSAMIDI
|
||||
AL_VAR(MIDI_DRIVER, midi_alsa);
|
||||
#define MIDI_DRIVER_ALSA \
|
||||
{ MIDI_ALSA, &midi_alsa, TRUE },
|
||||
#endif /* ALLEGRO_WITH_ALSAMIDI */
|
||||
|
||||
|
||||
#ifdef ALLEGRO_WITH_JACKDIGI
|
||||
AL_VAR(DIGI_DRIVER, digi_jack);
|
||||
#define DIGI_DRIVER_JACK \
|
||||
{ DIGI_JACK, &digi_jack, TRUE },
|
||||
#endif /* ALLEGRO_WITH_JACKDIGI */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/************************************/
|
||||
/************ X-specific ************/
|
||||
/************************************/
|
||||
|
@ -116,17 +116,3 @@ AL_VAR(GFX_DRIVER, gfx_gdi);
|
||||
{ GFX_DIRECTX_WIN, &gfx_directx_win, TRUE }, \
|
||||
{ GFX_DIRECTX_OVL, &gfx_directx_ovl, TRUE }, \
|
||||
{ GFX_GDI, &gfx_gdi, FALSE },
|
||||
|
||||
|
||||
|
||||
/********************************************/
|
||||
/*************** sound drivers **************/
|
||||
/********************************************/
|
||||
#define DIGI_DIRECTX(n) AL_ID('D','X','A'+(n),' ')
|
||||
#define DIGI_DIRECTAMX(n) AL_ID('A','X','A'+(n),' ')
|
||||
#define DIGI_WAVOUTID(n) AL_ID('W','O','A'+(n),' ')
|
||||
#define MIDI_WIN32MAPPER AL_ID('W','3','2','M')
|
||||
#define MIDI_WIN32(n) AL_ID('W','3','2','A'+(n))
|
||||
#define MIDI_WIN32_IN(n) AL_ID('W','3','2','A'+(n))
|
||||
|
||||
|
||||
|
@ -1,60 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* Sound support routines.
|
||||
*
|
||||
* By Shawn Hargreaves.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ALLEGRO_SOUND_H
|
||||
#define ALLEGRO_SOUND_H
|
||||
|
||||
#include "base.h"
|
||||
#include "digi.h"
|
||||
#include "stream.h"
|
||||
#include "midi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
AL_FUNC(void, reserve_voices, (int digi_voices, int midi_voices));
|
||||
AL_FUNC(void, set_volume_per_voice, (int scale));
|
||||
|
||||
AL_FUNC(int, install_sound, (int digi, int midi, AL_CONST char *cfg_path));
|
||||
AL_FUNC(void, remove_sound, (void));
|
||||
|
||||
AL_FUNC(int, install_sound_input, (int digi, int midi));
|
||||
AL_FUNC(void, remove_sound_input, (void));
|
||||
|
||||
AL_FUNC(void, set_volume, (int digi_volume, int midi_volume));
|
||||
AL_FUNC(void, set_hardware_volume, (int digi_volume, int midi_volume));
|
||||
|
||||
AL_FUNC(void, get_volume, (int *digi_volume, int *midi_volume));
|
||||
AL_FUNC(void, get_hardware_volume, (int *digi_volume, int *midi_volume));
|
||||
|
||||
AL_FUNC(void, set_mixer_quality, (int quality));
|
||||
AL_FUNC(int, get_mixer_quality, (void));
|
||||
AL_FUNC(int, get_mixer_frequency, (void));
|
||||
AL_FUNC(int, get_mixer_bits, (void));
|
||||
AL_FUNC(int, get_mixer_channels, (void));
|
||||
AL_FUNC(int, get_mixer_voices, (void));
|
||||
AL_FUNC(int, get_mixer_buffer_length, (void));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ifndef ALLEGRO_SOUND_H */
|
||||
|
||||
|
@ -1,52 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* Streaming sound routines.
|
||||
*
|
||||
* By Shawn Hargreaves.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ALLEGRO_STREAM_H
|
||||
#define ALLEGRO_STREAM_H
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct SAMPLE;
|
||||
|
||||
typedef struct AUDIOSTREAM
|
||||
{
|
||||
int voice; /* the voice we are playing on */
|
||||
struct SAMPLE *samp; /* the sample we are using */
|
||||
int len; /* buffer length */
|
||||
int bufcount; /* number of buffers per sample half */
|
||||
int bufnum; /* current refill buffer */
|
||||
int active; /* which half is currently playing */
|
||||
void *locked; /* the locked buffer */
|
||||
} AUDIOSTREAM;
|
||||
|
||||
AL_FUNC(AUDIOSTREAM *, play_audio_stream, (int len, int bits, int stereo, int freq, int vol, int pan));
|
||||
AL_FUNC(void, stop_audio_stream, (AUDIOSTREAM *stream));
|
||||
AL_FUNC(void *, get_audio_stream_buffer, (AUDIOSTREAM *stream));
|
||||
AL_FUNC(void, free_audio_stream_buffer, (AUDIOSTREAM *stream));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ifndef ALLEGRO_STREAM_H */
|
||||
|
||||
|
@ -230,8 +230,6 @@ typedef struct SYSTEM_DRIVER
|
||||
AL_METHOD(void, lock_mutex, (void *handle));
|
||||
AL_METHOD(void, unlock_mutex, (void *handle));
|
||||
AL_METHOD(_DRIVER_INFO *, gfx_drivers, (void));
|
||||
AL_METHOD(_DRIVER_INFO *, digi_drivers, (void));
|
||||
AL_METHOD(_DRIVER_INFO *, midi_drivers, (void));
|
||||
AL_METHOD(_DRIVER_INFO *, keyboard_drivers, (void));
|
||||
AL_METHOD(_DRIVER_INFO *, mouse_drivers, (void));
|
||||
AL_METHOD(_DRIVER_INFO *, timer_drivers, (void));
|
||||
|
@ -221,7 +221,6 @@ int (*_al_trace_handler)(AL_CONST char *msg) = NULL;
|
||||
* linked in, then the structure pointers will be null, so we don't need
|
||||
* to bother with that bit of code elsewhere.
|
||||
*/
|
||||
struct _AL_LINKER_MIDI *_al_linker_midi = NULL;
|
||||
struct _AL_LINKER_MOUSE *_al_linker_mouse = NULL;
|
||||
|
||||
|
||||
@ -308,14 +307,11 @@ static int _install_allegro(int system_id, int *errno_ptr, int (*atexit_ptr)(voi
|
||||
#ifndef ALLEGRO_USE_CONSTRUCTOR
|
||||
/* call constructor functions manually */
|
||||
extern void _initialize_datafile_types();
|
||||
extern void _midi_constructor();
|
||||
extern void _mouse_constructor();
|
||||
|
||||
_initialize_datafile_types();
|
||||
_midi_constructor();
|
||||
_mouse_constructor();
|
||||
_register_bitmap_file_type_init();
|
||||
_register_sample_file_type_init();
|
||||
_register_font_file_type_init();
|
||||
#endif
|
||||
|
||||
@ -758,7 +754,6 @@ SYSTEM_DRIVER system_none =
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
sys_no_driver, sys_no_driver, sys_no_driver,
|
||||
sys_no_driver, sys_no_driver, sys_no_driver
|
||||
sys_no_driver, sys_no_driver, sys_no_driver, sys_no_driver
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
|
||||
|
||||
static void unload_midi(MIDI *m);
|
||||
static void initialise_datafile(DATAFILE *data);
|
||||
|
||||
|
||||
@ -561,115 +560,6 @@ static RGB *read_palette(PACKFILE *f, int size)
|
||||
|
||||
|
||||
|
||||
/* read_sample:
|
||||
* Reads a sample from a file.
|
||||
*/
|
||||
static SAMPLE *read_sample(PACKFILE *f)
|
||||
{
|
||||
signed short bits;
|
||||
SAMPLE *s;
|
||||
|
||||
s = _AL_MALLOC(sizeof(SAMPLE));
|
||||
if (!s) {
|
||||
*allegro_errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bits = pack_mgetw(f);
|
||||
|
||||
if (bits < 0) {
|
||||
s->bits = -bits;
|
||||
s->stereo = TRUE;
|
||||
}
|
||||
else {
|
||||
s->bits = bits;
|
||||
s->stereo = FALSE;
|
||||
}
|
||||
|
||||
s->freq = pack_mgetw(f);
|
||||
s->len = pack_mgetl(f);
|
||||
s->priority = 128;
|
||||
s->loop_start = 0;
|
||||
s->loop_end = s->len;
|
||||
s->param = 0;
|
||||
|
||||
if (s->bits == 8) {
|
||||
s->data = read_block(f, s->len * ((s->stereo) ? 2 : 1), 0);
|
||||
}
|
||||
else {
|
||||
s->data = _AL_MALLOC_ATOMIC(s->len * sizeof(short) * ((s->stereo) ? 2 : 1));
|
||||
if (s->data) {
|
||||
int i;
|
||||
|
||||
for (i=0; i < (int)s->len * ((s->stereo) ? 2 : 1); i++) {
|
||||
((unsigned short *)s->data)[i] = pack_igetw(f);
|
||||
}
|
||||
|
||||
if (pack_ferror(f)) {
|
||||
_AL_FREE(s->data);
|
||||
s->data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!s->data) {
|
||||
_AL_FREE(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LOCK_DATA(s, sizeof(SAMPLE));
|
||||
LOCK_DATA(s->data, s->len * ((s->bits==8) ? 1 : sizeof(short)) * ((s->stereo) ? 2 : 1));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* read_midi:
|
||||
* Reads MIDI data from a datafile (this is not the same thing as the
|
||||
* standard midi file format).
|
||||
*/
|
||||
static MIDI *read_midi(PACKFILE *f)
|
||||
{
|
||||
MIDI *m;
|
||||
int c;
|
||||
|
||||
m = _AL_MALLOC(sizeof(MIDI));
|
||||
if (!m) {
|
||||
*allegro_errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (c=0; c<MIDI_TRACKS; c++) {
|
||||
m->track[c].len = 0;
|
||||
m->track[c].data = NULL;
|
||||
}
|
||||
|
||||
m->divisions = pack_mgetw(f);
|
||||
|
||||
for (c=0; c<MIDI_TRACKS; c++) {
|
||||
m->track[c].len = pack_mgetl(f);
|
||||
if (m->track[c].len > 0) {
|
||||
m->track[c].data = read_block(f, m->track[c].len, 0);
|
||||
if (!m->track[c].data) {
|
||||
unload_midi(m);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOCK_DATA(m, sizeof(MIDI));
|
||||
|
||||
for (c=0; c<MIDI_TRACKS; c++) {
|
||||
if (m->track[c].data) {
|
||||
LOCK_DATA(m->track[c].data, m->track[c].len);
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* read_rle_sprite:
|
||||
* Reads an RLE compressed sprite from a file, allocating memory for it.
|
||||
*/
|
||||
@ -953,18 +843,6 @@ static DATAFILE *read_old_datafile(PACKFILE *f, void (*callback)(DATAFILE *))
|
||||
dat[c].size = 0;
|
||||
break;
|
||||
|
||||
case V1_DAT_SAMPLE:
|
||||
dat[c].type = DAT_SAMPLE;
|
||||
dat[c].dat = read_sample(f);
|
||||
dat[c].size = 0;
|
||||
break;
|
||||
|
||||
case V1_DAT_MIDI:
|
||||
dat[c].type = DAT_MIDI;
|
||||
dat[c].dat = read_midi(f);
|
||||
dat[c].size = 0;
|
||||
break;
|
||||
|
||||
case V1_DAT_RLE_SPRITE:
|
||||
dat[c].type = DAT_RLE_SPRITE;
|
||||
dat[c].dat = read_rle_sprite(f, 8);
|
||||
@ -1040,26 +918,6 @@ static void *load_font_object(PACKFILE *f, long size)
|
||||
|
||||
|
||||
|
||||
/* load_sample_object:
|
||||
* Loads a sample object from a datafile.
|
||||
*/
|
||||
static void *load_sample_object(PACKFILE *f, long size)
|
||||
{
|
||||
return read_sample(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* load_midi_object:
|
||||
* Loads a midifile object from a datafile.
|
||||
*/
|
||||
static void *load_midi_object(PACKFILE *f, long size)
|
||||
{
|
||||
return read_midi(f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* load_bitmap_object:
|
||||
* Loads a bitmap object from a datafile.
|
||||
*/
|
||||
@ -1108,46 +966,6 @@ static void *load_xcompiled_sprite_object(PACKFILE *f, long size)
|
||||
|
||||
|
||||
|
||||
/* unload_sample:
|
||||
* Destroys a sample object.
|
||||
*/
|
||||
static void unload_sample(SAMPLE *s)
|
||||
{
|
||||
if (s) {
|
||||
if (s->data) {
|
||||
UNLOCK_DATA(s->data, s->len * ((s->bits==8) ? 1 : sizeof(short)) * ((s->stereo) ? 2 : 1));
|
||||
_AL_FREE(s->data);
|
||||
}
|
||||
|
||||
UNLOCK_DATA(s, sizeof(SAMPLE));
|
||||
_AL_FREE(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* unload_midi:
|
||||
* Destroys a MIDI object.
|
||||
*/
|
||||
static void unload_midi(MIDI *m)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (m) {
|
||||
for (c=0; c<MIDI_TRACKS; c++) {
|
||||
if (m->track[c].data) {
|
||||
UNLOCK_DATA(m->track[c].data, m->track[c].len);
|
||||
_AL_FREE(m->track[c].data);
|
||||
}
|
||||
}
|
||||
|
||||
UNLOCK_DATA(m, sizeof(MIDI));
|
||||
_AL_FREE(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* load_object:
|
||||
* Helper to load an object from a datafile and store it in 'obj'.
|
||||
* Returns 0 on success and -1 on failure.
|
||||
@ -2148,8 +1966,6 @@ static void initialise_datafile(DATAFILE *data)
|
||||
{
|
||||
int c, c2, color_flag;
|
||||
FONT *f;
|
||||
SAMPLE *s;
|
||||
MIDI *m;
|
||||
|
||||
for (c=0; data[c].type != DAT_END; c++) {
|
||||
|
||||
@ -2179,22 +1995,6 @@ static void initialise_datafile(DATAFILE *data)
|
||||
f->vtable = font_vtable_mono;
|
||||
}
|
||||
break;
|
||||
|
||||
case DAT_SAMPLE:
|
||||
s = data[c].dat;
|
||||
LOCK_DATA(s, sizeof(SAMPLE));
|
||||
LOCK_DATA(s->data, s->len * ((s->bits==8) ? 1 : sizeof(short)) * ((s->stereo) ? 2 : 1));
|
||||
break;
|
||||
|
||||
case DAT_MIDI:
|
||||
m = data[c].dat;
|
||||
LOCK_DATA(m, sizeof(MIDI));
|
||||
for (c2=0; c2<MIDI_TRACKS; c2++) {
|
||||
if (m->track[c2].data) {
|
||||
LOCK_DATA(m->track[c2].data, m->track[c2].len);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2225,8 +2025,6 @@ void _initialize_datafile_types(void)
|
||||
{
|
||||
register_datafile_object(DAT_FILE, load_file_object, (void (*)(void *data))unload_datafile );
|
||||
register_datafile_object(DAT_FONT, load_font_object, (void (*)(void *data))destroy_font );
|
||||
register_datafile_object(DAT_SAMPLE, load_sample_object, (void (*)(void *data))unload_sample );
|
||||
register_datafile_object(DAT_MIDI, load_midi_object, (void (*)(void *data))unload_midi );
|
||||
register_datafile_object(DAT_BITMAP, load_bitmap_object, (void (*)(void *data))destroy_bitmap );
|
||||
register_datafile_object(DAT_RLE_SPRITE, load_rle_sprite_object, (void (*)(void *data))destroy_rle_sprite );
|
||||
register_datafile_object(DAT_C_SPRITE, load_compiled_sprite_object, (void (*)(void *data))destroy_compiled_sprite);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,272 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* MacOS X Core Audio digital sound driver.
|
||||
*
|
||||
* By Angelo Mottola.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
#include "allegro.h"
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintosx.h"
|
||||
|
||||
#ifndef ALLEGRO_MACOSX
|
||||
#error something is wrong with the makefile
|
||||
#endif
|
||||
|
||||
|
||||
static int ca_detect(int);
|
||||
static int ca_init(int, int);
|
||||
static void ca_exit(int);
|
||||
static int ca_buffer_size();
|
||||
static int ca_set_mixer_volume(int);
|
||||
|
||||
|
||||
static AUGraph graph;
|
||||
static AudioUnit output_unit, converter_unit;
|
||||
static int audio_buffer_size = 0;
|
||||
static char ca_desc[512] = EMPTY_STRING;
|
||||
|
||||
|
||||
DIGI_DRIVER digi_core_audio =
|
||||
{
|
||||
DIGI_CORE_AUDIO,
|
||||
empty_string,
|
||||
empty_string,
|
||||
"CoreAudio",
|
||||
0,
|
||||
0,
|
||||
MIXER_MAX_SFX,
|
||||
MIXER_DEF_SFX,
|
||||
|
||||
ca_detect,
|
||||
ca_init,
|
||||
ca_exit,
|
||||
ca_set_mixer_volume,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
ca_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
|
||||
};
|
||||
|
||||
|
||||
|
||||
static OSStatus render_callback(void *inRefCon, AudioUnitRenderActionFlags *inActionFlags,
|
||||
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumFrames, AudioBufferList *ioData)
|
||||
{
|
||||
_mix_some_samples((unsigned long)ioData->mBuffers[0].mData, 0, TRUE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int ca_detect(int input)
|
||||
{
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return FALSE;
|
||||
}
|
||||
if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int ca_init(int input, int voices)
|
||||
{
|
||||
AudioDeviceID audio_device;
|
||||
ComponentDescription desc;
|
||||
AUNode output_node, converter_node;
|
||||
AURenderCallbackStruct render_cb;
|
||||
UInt32 property_size, buffer_size;
|
||||
AudioStreamBasicDescription input_format_desc, output_format_desc;
|
||||
char device_name[64], manufacturer[64];
|
||||
UInt32 device_name_size, manufacturer_size;
|
||||
char tmp1[256], tmp2[256], tmp3[256];
|
||||
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return -1;
|
||||
}
|
||||
if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("MacOS X.2 or newer required by this driver"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
NewAUGraph(&graph);
|
||||
|
||||
desc.componentType = kAudioUnitType_FormatConverter;
|
||||
desc.componentSubType = kAudioUnitSubType_AUConverter;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
AUGraphNewNode(graph, &desc, 0, NULL, &converter_node);
|
||||
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
AUGraphNewNode(graph, &desc, 0, NULL, &output_node);
|
||||
|
||||
AUGraphOpen(graph);
|
||||
AUGraphInitialize(graph);
|
||||
|
||||
AUGraphGetNodeInfo(graph, output_node, NULL, NULL, NULL, &output_unit);
|
||||
AUGraphGetNodeInfo(graph, converter_node, NULL, NULL, NULL, &converter_unit);
|
||||
|
||||
property_size = sizeof(output_format_desc);
|
||||
if (AudioUnitGetProperty(output_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &output_format_desc, &property_size)) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot detect output audio format"));
|
||||
ca_exit(FALSE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
input_format_desc.mSampleRate = output_format_desc.mSampleRate;
|
||||
input_format_desc.mFormatID = kAudioFormatLinearPCM;
|
||||
#ifdef ALLEGRO_BIG_ENDIAN
|
||||
input_format_desc.mFormatFlags = kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
|
||||
#else
|
||||
input_format_desc.mFormatFlags = kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
|
||||
#endif
|
||||
input_format_desc.mBytesPerPacket = 4;
|
||||
input_format_desc.mFramesPerPacket = 1;
|
||||
input_format_desc.mBytesPerFrame = 4;
|
||||
input_format_desc.mChannelsPerFrame = 2;
|
||||
input_format_desc.mBitsPerChannel = 16;
|
||||
|
||||
if (AudioUnitSetProperty(converter_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &output_format_desc, sizeof(output_format_desc)) ||
|
||||
AudioUnitSetProperty(converter_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &input_format_desc, sizeof(input_format_desc))) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot configure format converter audio unit"));
|
||||
ca_exit(FALSE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_sound_bits = 16;
|
||||
_sound_stereo = TRUE;
|
||||
_sound_freq = (int)output_format_desc.mSampleRate;
|
||||
|
||||
AUGraphConnectNodeInput(graph, converter_node, 0, output_node, 0);
|
||||
|
||||
render_cb.inputProc = render_callback;
|
||||
render_cb.inputProcRefCon = NULL;
|
||||
if (AudioUnitSetProperty(converter_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &render_cb, sizeof(render_cb))) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot set audio rendering callback"));
|
||||
ca_exit(FALSE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
property_size = sizeof(audio_device);
|
||||
if (AudioUnitGetProperty(output_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Output, 0, &audio_device, &property_size)) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot get CoreAudio device"));
|
||||
ca_exit(FALSE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
property_size = sizeof(buffer_size);
|
||||
if (AudioDeviceGetProperty(audio_device, 0, false, kAudioDevicePropertyBufferSize, &property_size, &buffer_size)) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot get CoreAudio device buffer size"));
|
||||
ca_exit(FALSE);
|
||||
return -1;
|
||||
}
|
||||
audio_buffer_size = buffer_size / sizeof(float) * sizeof(short);
|
||||
digi_core_audio.voices = voices;
|
||||
if (_mixer_init(audio_buffer_size / sizeof(short), _sound_freq, _sound_stereo, TRUE, &digi_core_audio.voices)) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Error initializing mixer"));
|
||||
ca_exit(FALSE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AUGraphStart(graph);
|
||||
|
||||
device_name_size = sizeof(device_name);
|
||||
manufacturer_size = sizeof(manufacturer);
|
||||
if (!AudioDeviceGetProperty(audio_device, 0, false, kAudioDevicePropertyDeviceName, &device_name_size, device_name) &&
|
||||
!AudioDeviceGetProperty(audio_device, 0, false, kAudioDevicePropertyDeviceManufacturer, &manufacturer_size, manufacturer)) {
|
||||
uszprintf(ca_desc, sizeof(ca_desc), get_config_text("%s (%s), 16 bits (%d real), %d bps, %s"),
|
||||
uconvert_ascii(device_name, tmp1), uconvert_ascii(manufacturer, tmp2), output_format_desc.mBitsPerChannel,
|
||||
_sound_freq, uconvert_ascii(_sound_stereo ? "stereo" : "mono", tmp3));
|
||||
}
|
||||
else {
|
||||
uszprintf(ca_desc, sizeof(ca_desc), get_config_text("16 bits (%d real), %d bps, %s"), output_format_desc.mBitsPerChannel,
|
||||
_sound_freq, uconvert_ascii(_sound_stereo ? "stereo" : "mono", tmp3));
|
||||
}
|
||||
digi_core_audio.desc = ca_desc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ca_exit(int input)
|
||||
{
|
||||
if (input)
|
||||
return;
|
||||
AUGraphStop(graph);
|
||||
AUGraphUninitialize(graph);
|
||||
AUGraphClose(graph);
|
||||
DisposeAUGraph(graph);
|
||||
_mixer_exit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int ca_buffer_size()
|
||||
{
|
||||
return audio_buffer_size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int ca_set_mixer_volume(int volume)
|
||||
{
|
||||
float value = (float)volume / 255.0;
|
||||
|
||||
return AudioUnitSetParameter(converter_unit, kAudioUnitParameterUnit_LinearGain, kAudioUnitScope_Output, 0, value, 0);
|
||||
}
|
||||
|
@ -1,187 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* CoreAudio MIDI driver routines for MacOS X.
|
||||
*
|
||||
* By Angelo Mottola.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
#include "allegro.h"
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintosx.h"
|
||||
|
||||
#ifndef ALLEGRO_MACOSX
|
||||
#error something is wrong with the makefile
|
||||
#endif
|
||||
|
||||
|
||||
static int ca_detect(int);
|
||||
static int ca_init(int, int);
|
||||
static void ca_exit(int);
|
||||
static int ca_set_mixer_volume(int);
|
||||
static void ca_raw_midi(int);
|
||||
|
||||
|
||||
static AUGraph graph;
|
||||
static AudioUnit synth_unit;
|
||||
static int command, data_pos, data_buffer[2];
|
||||
static char driver_desc[256];
|
||||
|
||||
|
||||
MIDI_DRIVER midi_core_audio =
|
||||
{
|
||||
MIDI_CORE_AUDIO, /* driver ID code */
|
||||
empty_string, /* driver name */
|
||||
empty_string, /* description string */
|
||||
"CoreAudio", /* ASCII format name string */
|
||||
16, /* available voices */
|
||||
0, /* voice number offset */
|
||||
16, /* maximum voices we can support */
|
||||
0, /* default number of voices to use */
|
||||
10, 10, /* reserved voice range */
|
||||
ca_detect, /* AL_METHOD(int, detect, (int input)); */
|
||||
ca_init, /* AL_METHOD(int, init, (int input, int voices)); */
|
||||
ca_exit, /* AL_METHOD(void, exit, (int input)); */
|
||||
ca_set_mixer_volume, /* AL_METHOD(int, mixer_set_volume, (int volume)); */
|
||||
NULL, /* AL_METHOD(int, mixer_get_volume, (void)); */
|
||||
ca_raw_midi, /* AL_METHOD(void, raw_midi, (int data)); */
|
||||
_dummy_load_patches, /* AL_METHOD(int, load_patches, (AL_CONST char *patches, AL_CONST char *drums)); */
|
||||
_dummy_adjust_patches, /* AL_METHOD(void, adjust_patches, (AL_CONST char *patches, AL_CONST char *drums)); */
|
||||
_dummy_key_on, /* AL_METHOD(void, key_on, (int inst, int note, int bend, int vol, int pan)); */
|
||||
_dummy_noop1, /* AL_METHOD(void, key_off, (int voice)); */
|
||||
_dummy_noop2, /* AL_METHOD(void, set_volume, (int voice, int vol)); */
|
||||
_dummy_noop3, /* AL_METHOD(void, set_pitch, (int voice, int note, int bend)); */
|
||||
_dummy_noop2, /* AL_METHOD(void, set_pan, (int voice, int pan)); */
|
||||
_dummy_noop2, /* AL_METHOD(void, set_vibrato, (int voice, int amount)); */
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int ca_detect(int input)
|
||||
{
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return FALSE;
|
||||
}
|
||||
if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int ca_init(int input, int voices)
|
||||
{
|
||||
char tmp[128], tmp1[128], tmp2[128];
|
||||
char *sound = uconvert_ascii("sound", tmp);
|
||||
ComponentDescription desc;
|
||||
AUNode synth_node, output_node;
|
||||
UInt32 quality, reverb_type;
|
||||
int reverb;
|
||||
struct {
|
||||
UInt32 type;
|
||||
char *name;
|
||||
} reverb_info[6] = { { kReverbRoomType_SmallRoom, "small room" },
|
||||
{ kReverbRoomType_MediumRoom, "medium room" },
|
||||
{ kReverbRoomType_LargeRoom, "large room" },
|
||||
{ kReverbRoomType_MediumHall, "medium hall" },
|
||||
{ kReverbRoomType_LargeHall, "large hall" },
|
||||
{ kReverbRoomType_Plate, "plate" } };
|
||||
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return -1;
|
||||
}
|
||||
if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("MacOS X.2 or newer required by this driver"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
NewAUGraph(&graph);
|
||||
|
||||
desc.componentType = kAudioUnitType_MusicDevice;
|
||||
desc.componentSubType = kAudioUnitSubType_DLSSynth;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
AUGraphNewNode(graph, &desc, 0, NULL, &synth_node);
|
||||
|
||||
desc.componentType = kAudioUnitType_Output;
|
||||
desc.componentSubType = kAudioUnitSubType_DefaultOutput;
|
||||
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
AUGraphNewNode(graph, &desc, 0, NULL, &output_node);
|
||||
|
||||
AUGraphConnectNodeInput(graph, synth_node, 0, output_node, 0);
|
||||
|
||||
AUGraphOpen(graph);
|
||||
AUGraphInitialize(graph);
|
||||
|
||||
AUGraphGetNodeInfo(graph, synth_node, NULL, NULL, NULL, &synth_unit);
|
||||
|
||||
quality = CLAMP(0, get_config_int(sound, uconvert_ascii("ca_midi_quality", tmp), 127), 127);
|
||||
AudioUnitSetProperty(synth_unit, kAudioUnitProperty_RenderQuality, kAudioUnitScope_Output, 0, &quality, sizeof(quality));
|
||||
|
||||
reverb = CLAMP(0, get_config_int(sound, uconvert_ascii("ca_midi_reverb", tmp), 0), 5);
|
||||
reverb_type = reverb_info[reverb].type;
|
||||
AudioUnitSetProperty(synth_unit, kAudioUnitProperty_ReverbRoomType, kAudioUnitScope_Output, 0, &reverb_type, sizeof(reverb_type));
|
||||
|
||||
AUGraphStart(graph);
|
||||
|
||||
uszprintf(driver_desc, sizeof(driver_desc), uconvert_ascii("DLSMusicDevice unit, %s quality, %s reverb", tmp),
|
||||
(quality < 32 ? uconvert_ascii("low", tmp1) : (quality >= 96 ? uconvert_ascii("high", tmp1) : uconvert_ascii("medium", tmp1))),
|
||||
uconvert_ascii(reverb_info[reverb].name, tmp2));
|
||||
midi_core_audio.desc = driver_desc;
|
||||
|
||||
command = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ca_exit(int input)
|
||||
{
|
||||
if (input)
|
||||
return;
|
||||
AUGraphStop(graph);
|
||||
AUGraphUninitialize(graph);
|
||||
AUGraphClose(graph);
|
||||
DisposeAUGraph(graph);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int ca_set_mixer_volume(int volume)
|
||||
{
|
||||
float value = (float)volume / 255.0;
|
||||
|
||||
return AudioUnitSetParameter(synth_unit, kAudioUnitParameterUnit_LinearGain, kAudioUnitScope_Output, 0, value, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ca_raw_midi(int data)
|
||||
{
|
||||
if (command == -1) {
|
||||
data_buffer[0] = data_buffer[1] = 0;
|
||||
data_pos = 0;
|
||||
command = data;
|
||||
return;
|
||||
}
|
||||
data_buffer[data_pos++] = data;
|
||||
if (((data_pos == 1) && (((command >> 4) == 0xC) || ((command >> 4) == 0xD))) || (data_pos == 2)) {
|
||||
MusicDeviceMIDIEvent(synth_unit, command, data_buffer[0], data_buffer[1], 0);
|
||||
command = -1;
|
||||
}
|
||||
}
|
@ -50,15 +50,3 @@ BEGIN_GFX_DRIVER_LIST
|
||||
{ GFX_QUARTZ_FULLSCREEN, &gfx_quartz_full, TRUE },
|
||||
{ GFX_QUARTZ_WINDOW, &gfx_quartz_window, TRUE },
|
||||
END_GFX_DRIVER_LIST
|
||||
|
||||
|
||||
BEGIN_DIGI_DRIVER_LIST
|
||||
{ DIGI_CORE_AUDIO, &digi_core_audio, TRUE },
|
||||
{ DIGI_SOUND_MANAGER, &digi_sound_manager, TRUE },
|
||||
END_DIGI_DRIVER_LIST
|
||||
|
||||
|
||||
BEGIN_MIDI_DRIVER_LIST
|
||||
{ MIDI_CORE_AUDIO, &midi_core_audio, TRUE },
|
||||
{ MIDI_QUICKTIME, &midi_quicktime, TRUE },
|
||||
END_MIDI_DRIVER_LIST
|
||||
|
@ -1,273 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* QuickTime MIDI driver routines for MacOS X.
|
||||
*
|
||||
* By Ronaldo Hideki Yamada.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
#include "allegro.h"
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintosx.h"
|
||||
|
||||
#ifndef ALLEGRO_MACOSX
|
||||
#error something is wrong with the makefile
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct MIDI_VOICE
|
||||
{
|
||||
NoteChannel channel;
|
||||
int note;
|
||||
int bend;
|
||||
int inst;
|
||||
int vol;
|
||||
int pan;
|
||||
} MIDI_VOICE;
|
||||
|
||||
|
||||
static NoteAllocator note_allocator = NULL;
|
||||
static MIDI_VOICE voice[17];
|
||||
static char driver_desc[256];
|
||||
|
||||
|
||||
static int osx_midi_detect(int input);
|
||||
static int osx_midi_init(int input, int voices);
|
||||
static void osx_midi_exit(int input);
|
||||
static int osx_midi_set_mixer_volume(int volume);
|
||||
static void osx_midi_key_on(int inst, int note, int bend, int vol, int pan);
|
||||
static void osx_midi_key_off(int voice);
|
||||
static void osx_midi_set_volume(int voice, int vol);
|
||||
static void osx_midi_set_pitch(int voice, int note, int bend);
|
||||
static void osx_midi_set_pan(int voice, int pan);
|
||||
|
||||
|
||||
MIDI_DRIVER midi_quicktime =
|
||||
{
|
||||
MIDI_QUICKTIME, /* driver ID code */
|
||||
empty_string, /* driver name */
|
||||
empty_string, /* description string */
|
||||
"QuickTime MIDI", /* ASCII format name string */
|
||||
16, /* available voices */
|
||||
0, /* voice number offset */
|
||||
16, /* maximum voices we can support */
|
||||
0, /* default number of voices to use */
|
||||
10, 10, /* reserved voice range */
|
||||
osx_midi_detect, /* AL_METHOD(int, detect, (int input)); */
|
||||
osx_midi_init, /* AL_METHOD(int, init, (int input, int voices)); */
|
||||
osx_midi_exit, /* AL_METHOD(void, exit, (int input)); */
|
||||
osx_midi_set_mixer_volume, /* AL_METHOD(int, set_mixer_volume, (int volume)); */
|
||||
NULL, /* AL_METHOD(int, get_mixer_volume, (void)); */
|
||||
NULL, /* AL_METHOD(void, raw_midi, (int data)); */
|
||||
_dummy_load_patches, /* AL_METHOD(int, load_patches, (AL_CONST char *patches, AL_CONST char *drums)); */
|
||||
_dummy_adjust_patches, /* AL_METHOD(void, adjust_patches, (AL_CONST char *patches, AL_CONST char *drums)); */
|
||||
osx_midi_key_on, /* AL_METHOD(void, key_on, (int inst, int note, int bend, int vol, int pan)); */
|
||||
osx_midi_key_off, /* AL_METHOD(void, key_off, (int voice)); */
|
||||
osx_midi_set_volume, /* AL_METHOD(void, set_volume, (int voice, int vol)); */
|
||||
osx_midi_set_pitch, /* AL_METHOD(void, set_pitch, (int voice, int note, int bend)); */
|
||||
osx_midi_set_pan, /* AL_METHOD(void, set_pan, (int voice, int pan)); */
|
||||
_dummy_noop2, /* AL_METHOD(void, set_vibrato, (int voice, int amount)); */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* osx_midi_detect:
|
||||
* QuickTime Music MIDI detection.
|
||||
*/
|
||||
static int osx_midi_detect(int input)
|
||||
{
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return FALSE;
|
||||
}
|
||||
note_allocator = OpenDefaultComponent(kNoteAllocatorComponentType, 0);
|
||||
if (!note_allocator)
|
||||
return FALSE;
|
||||
CloseComponent(note_allocator);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_midi_init:
|
||||
* Initializes the QuickTime Music MIDI driver.
|
||||
*/
|
||||
static int osx_midi_init(int input, int voices)
|
||||
{
|
||||
NoteRequest note_request;
|
||||
ComponentResult result;
|
||||
char tmp[256];
|
||||
int i;
|
||||
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return -1;
|
||||
}
|
||||
note_allocator = OpenDefaultComponent(kNoteAllocatorComponentType, 0);
|
||||
if(!note_allocator) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Cannot open the NoteAllocator QuickTime component"));
|
||||
return -1;
|
||||
}
|
||||
memset(voice, 0, 17 * sizeof(MIDI_VOICE));
|
||||
for(i = 1; i <= 16; i++) {
|
||||
voice[i].note = -1;
|
||||
voice[i].bend = -1;
|
||||
voice[i].inst = -1;
|
||||
voice[i].vol = -1;
|
||||
voice[i].pan = -1;
|
||||
memset(¬e_request, 0, sizeof(note_request));
|
||||
#if TARGET_RT_BIG_ENDIAN
|
||||
note_request.info.polyphony = 8;
|
||||
note_request.info.typicalPolyphony = 0x00010000;
|
||||
#else
|
||||
note_request.info.polyphony.bigEndianValue = EndianU16_NtoB(8);
|
||||
note_request.info.typicalPolyphony.bigEndianValue = EndianS32_NtoB(X2Fix(1.0));
|
||||
#endif
|
||||
result = NAStuffToneDescription(note_allocator, 1, ¬e_request.tone);
|
||||
result |= NANewNoteChannel(note_allocator, ¬e_request, &voice[i].channel);
|
||||
result |= NAResetNoteChannel(note_allocator, voice[i].channel);
|
||||
if ((result) || (!voice[i].channel)) {
|
||||
osx_midi_exit(input);
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Failed initializing MIDI channels"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
uszprintf(driver_desc, sizeof(driver_desc), uconvert_ascii("QuickTime Music MIDI synthesizer", tmp));
|
||||
midi_quicktime.desc = driver_desc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_midi_exit:
|
||||
* Shuts down QuickTime Music MIDI subsystem.
|
||||
*/
|
||||
static void osx_midi_exit(int input)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (input)
|
||||
return;
|
||||
|
||||
if (note_allocator) {
|
||||
for(i = 1; i <= 16; i++) {
|
||||
if (voice[i].channel) {
|
||||
NAPlayNote(note_allocator, voice[i].channel, voice[i].note, 0);
|
||||
NADisposeNoteChannel(note_allocator, voice[i].channel);
|
||||
voice[i].channel = 0;
|
||||
}
|
||||
}
|
||||
CloseComponent(note_allocator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_midi_set_mixer_volume:
|
||||
* Sets QuickTime Music MIDI volume multiplier for all channels.
|
||||
*/
|
||||
static int osx_midi_set_mixer_volume(int volume)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= 16; i++) {
|
||||
if (NASetNoteChannelVolume(note_allocator, voice[i].channel, volume << 8))
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_midi_key_on:
|
||||
* Triggers a specified voice.
|
||||
*/
|
||||
static void osx_midi_key_on(int inst, int note, int bend, int vol, int pan)
|
||||
{
|
||||
int voice_id;
|
||||
NoteChannel channel;
|
||||
|
||||
if (inst > 127) {
|
||||
/* Percussion */
|
||||
note = inst - 128;
|
||||
inst = kFirstDrumkit + 1;
|
||||
}
|
||||
else
|
||||
inst = kFirstGMInstrument + inst;
|
||||
voice_id = _midi_allocate_voice(1, 16);
|
||||
if (voice_id < 0)
|
||||
return;
|
||||
channel = voice[voice_id].channel;
|
||||
if (voice[voice_id].inst != inst) {
|
||||
if (NASetInstrumentNumber(note_allocator, channel, inst) != noErr)
|
||||
return;
|
||||
voice[voice_id].inst = inst;
|
||||
}
|
||||
NAPlayNote(note_allocator, channel, voice[voice_id].note, 0);
|
||||
if (NAPlayNote(note_allocator, channel, note, vol) != noErr)
|
||||
return;
|
||||
voice[voice_id].note = note;
|
||||
osx_midi_set_pitch(voice_id, note, bend);
|
||||
osx_midi_set_pan(voice_id, pan);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_midi_key_off:
|
||||
* Turns off specified voice.
|
||||
*/
|
||||
static void osx_midi_key_off(int voice_id)
|
||||
{
|
||||
NAPlayNote(note_allocator, voice[voice_id].channel, voice[voice_id].note, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_midi_set_volume:
|
||||
* Sets volume for a specified voice.
|
||||
*/
|
||||
static void osx_midi_set_volume(int voice_id, int vol)
|
||||
{
|
||||
if (voice[voice_id].vol != vol) {
|
||||
if (NASetController(note_allocator, voice[voice_id].channel, kControllerVolume, vol << 7) == noErr)
|
||||
voice[voice_id].vol = vol;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_midi_set_pitch:
|
||||
* Sets pitch of specified voice.
|
||||
*/
|
||||
static void osx_midi_set_pitch(int voice_id, int note, int bend)
|
||||
{
|
||||
bend >>= 5;
|
||||
if (voice[voice_id].bend != bend) {
|
||||
if (NASetController(note_allocator, voice[voice_id].channel, kControllerPitchBend, bend) == noErr)
|
||||
voice[voice_id].bend = bend;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_midi_set_pan:
|
||||
* Sets pan value on specified voice.
|
||||
*/
|
||||
static void osx_midi_set_pan(int voice_id, int pan)
|
||||
{
|
||||
if (voice[voice_id].pan != pan) {
|
||||
if (NASetNoteChannelBalance(note_allocator, voice[voice_id].channel, pan - 127) == noErr)
|
||||
voice[voice_id].pan = pan;
|
||||
}
|
||||
}
|
@ -1,293 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* MacOS X Sound Manager digital sound driver.
|
||||
*
|
||||
* By Angelo Mottola.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
#include "allegro.h"
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintosx.h"
|
||||
|
||||
#ifndef ALLEGRO_MACOSX
|
||||
#error something is wrong with the makefile
|
||||
#endif
|
||||
|
||||
|
||||
#define SAMPLES_PER_BUFFER 4096
|
||||
|
||||
|
||||
static int osx_digi_sound_detect(int);
|
||||
static int osx_digi_sound_init(int, int);
|
||||
static void osx_digi_sound_exit(int);
|
||||
static int osx_digi_sound_buffer_size();
|
||||
static int osx_digi_sound_set_mixer_volume(int);
|
||||
|
||||
|
||||
static SndChannel *sound_channel = NULL;
|
||||
static ExtSoundHeader sound_header;
|
||||
static unsigned char *sound_buffer[2] = { NULL, NULL };
|
||||
static char sound_desc[256];
|
||||
|
||||
|
||||
DIGI_DRIVER digi_sound_manager =
|
||||
{
|
||||
DIGI_SOUND_MANAGER,
|
||||
empty_string,
|
||||
empty_string,
|
||||
"Sound Manager",
|
||||
0,
|
||||
0,
|
||||
MIXER_MAX_SFX,
|
||||
MIXER_DEF_SFX,
|
||||
|
||||
osx_digi_sound_detect,
|
||||
osx_digi_sound_init,
|
||||
osx_digi_sound_exit,
|
||||
osx_digi_sound_set_mixer_volume,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
osx_digi_sound_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
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* sound_callback:
|
||||
* Sound Manager channel callback to update sound data.
|
||||
*/
|
||||
static void sound_callback(SndChannel *channel, SndCommand *command)
|
||||
{
|
||||
SndCommand new_command;
|
||||
|
||||
/* Send mixed buffer to sound card */
|
||||
sound_header.samplePtr = (Ptr)sound_buffer[command->param1];
|
||||
new_command.cmd = bufferCmd;
|
||||
new_command.param1 = 0;
|
||||
new_command.param2 = (long)&sound_header;
|
||||
if (SndDoCommand(channel, &new_command, FALSE) != noErr)
|
||||
return;
|
||||
|
||||
/* Mix the other buffer */
|
||||
command->param1 ^= 1;
|
||||
_mix_some_samples((unsigned long)sound_buffer[command->param1], 0, (_sound_bits == 16) ? TRUE : FALSE);
|
||||
|
||||
/* Reissue the callback */
|
||||
new_command.cmd = callBackCmd;
|
||||
new_command.param1 = command->param1;
|
||||
SndDoCommand(channel, &new_command, FALSE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_digi_sound_detect.
|
||||
* Returns TRUE if Sound Manager 3.x or newer is available.
|
||||
*/
|
||||
static int osx_digi_sound_detect(int input)
|
||||
{
|
||||
NumVersion version;
|
||||
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return FALSE;
|
||||
}
|
||||
version = SndSoundManagerVersion();
|
||||
if (version.majorRev < 3)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_digi_sound_init:
|
||||
* Initializes the sound driver.
|
||||
*/
|
||||
static int osx_digi_sound_init(int input, int voices)
|
||||
{
|
||||
SndCommand command;
|
||||
NumVersion version;
|
||||
long sound_caps = 0;
|
||||
char tmp[128];
|
||||
int i;
|
||||
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
version = SndSoundManagerVersion();
|
||||
if (version.majorRev < 3) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Sound Manager version 3.0 or newer required"));
|
||||
return -1;
|
||||
}
|
||||
Gestalt(gestaltSoundAttr, &sound_caps);
|
||||
|
||||
if (_sound_stereo >= 0) {
|
||||
if (_sound_stereo && (sound_caps & (1 << gestaltStereoCapability))) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Stereo output not supported"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
_sound_stereo = (sound_caps & (1 << gestaltStereoCapability)) ? TRUE : FALSE;
|
||||
if (_sound_bits >= 0) {
|
||||
if (_sound_bits != ((sound_caps & (1 << gestalt16BitAudioSupport)) ? 16 : 8)) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("16 bit output not supported"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
_sound_bits = (sound_caps & (1 << gestalt16BitAudioSupport)) ? 16 : 8;
|
||||
if (_sound_freq <= 0)
|
||||
_sound_freq = 44100;
|
||||
|
||||
memset(&sound_header, 0, sizeof(sound_header));
|
||||
sound_header.numChannels = (_sound_stereo) ? 2 : 1;
|
||||
sound_header.sampleRate = _sound_freq << 16;
|
||||
sound_header.encode = extSH;
|
||||
sound_header.numFrames = SAMPLES_PER_BUFFER;
|
||||
sound_header.sampleSize = _sound_bits;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
sound_buffer[i] = (unsigned char *)calloc(1, SAMPLES_PER_BUFFER * (_sound_bits / 8) * (_sound_stereo ? 2 : 1));
|
||||
if (!sound_buffer[i]) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory"));
|
||||
osx_digi_sound_exit(input);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
digi_sound_manager.voices = voices;
|
||||
if (_mixer_init(SAMPLES_PER_BUFFER * (_sound_stereo ? 2 : 1), _sound_freq, _sound_stereo, ((_sound_bits == 16) ? TRUE: FALSE), &digi_sound_manager.voices)) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Error initializing mixer"));
|
||||
osx_digi_sound_exit(input);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sound_channel = (SndChannel *)malloc(sizeof(SndChannel));
|
||||
if (!sound_channel) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory"));
|
||||
osx_digi_sound_exit(input);
|
||||
return -1;
|
||||
}
|
||||
sound_channel->qLength = 128;
|
||||
|
||||
if (SndNewChannel(&sound_channel, sampledSynth, (_sound_stereo ? initStereo : initMono), sound_callback) != noErr) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Failed creating sound channel"));
|
||||
free(sound_channel);
|
||||
return -1;
|
||||
}
|
||||
|
||||
command.cmd = callBackCmd;
|
||||
command.param1 = 0;
|
||||
SndDoCommand(sound_channel, &command, FALSE);
|
||||
|
||||
uszprintf(sound_desc, sizeof(sound_desc), get_config_text("Sound Manager version %d.%d, %d bits, %d bps, %s"),
|
||||
((version.majorRev / 16) * 10) + (version.majorRev & 0xf),
|
||||
(version.minorAndBugRev / 16), _sound_bits, _sound_freq,
|
||||
uconvert_ascii(_sound_stereo ? "stereo" : "mono", tmp));
|
||||
digi_sound_manager.desc = sound_desc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_digi_sound_exit:
|
||||
* Shuts down the sound driver.
|
||||
*/
|
||||
static void osx_digi_sound_exit(int input)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (input)
|
||||
return;
|
||||
|
||||
if (sound_channel) {
|
||||
SndDisposeChannel(sound_channel, TRUE);
|
||||
free(sound_channel);
|
||||
sound_channel = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (sound_buffer[i]) {
|
||||
free(sound_buffer[i]);
|
||||
sound_buffer[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
_mixer_exit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_digi_sound_buffer_size:
|
||||
* Returns the mixing buffer size, for use by the audiostream code.
|
||||
*/
|
||||
static int osx_digi_sound_buffer_size()
|
||||
{
|
||||
return SAMPLES_PER_BUFFER;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* osx_digi_sound_set_mixer_volume:
|
||||
* Sets the sound channel volume.
|
||||
*/
|
||||
static int osx_digi_sound_set_mixer_volume(int volume)
|
||||
{
|
||||
SndCommand command;
|
||||
|
||||
if (!sound_channel)
|
||||
return -1;
|
||||
|
||||
command.cmd = volumeCmd;
|
||||
command.param1 = 0;
|
||||
command.param2 = (volume << 16) | volume;
|
||||
return (SndDoCommand(sound_channel, &command, FALSE) != noErr);
|
||||
}
|
@ -121,8 +121,6 @@ SYSTEM_DRIVER system_macosx =
|
||||
_unix_lock_mutex,
|
||||
_unix_unlock_mutex,
|
||||
NULL, /* AL_METHOD(_DRIVER_INFO *, gfx_drivers, (void)); */
|
||||
NULL, /* AL_METHOD(_DRIVER_INFO *, digi_drivers, (void)); */
|
||||
NULL, /* AL_METHOD(_DRIVER_INFO *, midi_drivers, (void)); */
|
||||
NULL, /* AL_METHOD(_DRIVER_INFO *, keyboard_drivers, (void)); */
|
||||
NULL, /* AL_METHOD(_DRIVER_INFO *, mouse_drivers, (void)); */
|
||||
NULL, /* AL_METHOD(_DRIVER_INFO *, timer_drivers, (void)); */
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,197 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* Top level sample type registration routines.
|
||||
*
|
||||
* By Vincent Penquerc'h.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "allegro.h"
|
||||
#include "allegro/internal/aintern.h"
|
||||
|
||||
|
||||
|
||||
typedef struct SAMPLE_TYPE_INFO
|
||||
{
|
||||
char *ext;
|
||||
SAMPLE *(*load)(AL_CONST char *filename);
|
||||
int (*save)(AL_CONST char *filename, SAMPLE *smp);
|
||||
struct SAMPLE_TYPE_INFO *next;
|
||||
} SAMPLE_TYPE_INFO;
|
||||
|
||||
static SAMPLE_TYPE_INFO *sample_type_list = NULL;
|
||||
|
||||
|
||||
|
||||
/* register_sample_file_type:
|
||||
* Informs Allegro of a new sample file type, telling it how to load and
|
||||
* save files of this format (either function may be NULL).
|
||||
*/
|
||||
void register_sample_file_type(AL_CONST char *ext, SAMPLE *(*load)(AL_CONST char *filename), int (*save)(AL_CONST char *filename, SAMPLE *smp))
|
||||
{
|
||||
char tmp[32], *aext;
|
||||
SAMPLE_TYPE_INFO *iter = sample_type_list;
|
||||
ASSERT(ext);
|
||||
|
||||
aext = uconvert_toascii(ext, tmp);
|
||||
if (strlen(aext) == 0) return;
|
||||
|
||||
if (!iter)
|
||||
iter = sample_type_list = _AL_MALLOC(sizeof(struct SAMPLE_TYPE_INFO));
|
||||
else {
|
||||
for (iter = sample_type_list; iter->next; iter = iter->next);
|
||||
iter = iter->next = _AL_MALLOC(sizeof(struct SAMPLE_TYPE_INFO));
|
||||
}
|
||||
|
||||
if (iter) {
|
||||
iter->load = load;
|
||||
iter->save = save;
|
||||
iter->ext = _al_strdup(aext);
|
||||
iter->next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* load_sample:
|
||||
* Loads a sample from disk.
|
||||
*/
|
||||
SAMPLE *load_sample(AL_CONST char *filename)
|
||||
{
|
||||
char tmp[32], *aext;
|
||||
SAMPLE_TYPE_INFO *iter;
|
||||
ASSERT(filename);
|
||||
|
||||
aext = uconvert_toascii(get_extension(filename), tmp);
|
||||
|
||||
for (iter = sample_type_list; iter; iter = iter->next) {
|
||||
if (stricmp(iter->ext, aext) == 0) {
|
||||
if (iter->load)
|
||||
return iter->load(filename);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* save_sample:
|
||||
* Writes a sample to disk.
|
||||
*/
|
||||
int save_sample(AL_CONST char *filename, SAMPLE *smp)
|
||||
{
|
||||
char tmp[32], *aext;
|
||||
SAMPLE_TYPE_INFO *iter;
|
||||
ASSERT(filename);
|
||||
ASSERT(smp);
|
||||
|
||||
aext = uconvert_toascii(get_extension(filename), tmp);
|
||||
|
||||
for (iter = sample_type_list; iter; iter = iter->next) {
|
||||
if (stricmp(iter->ext, aext) == 0) {
|
||||
if (iter->save)
|
||||
return iter->save(filename, smp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* register_sample_file_type_exit:
|
||||
* Free list of registered sample file types.
|
||||
*/
|
||||
static void register_sample_file_type_exit(void)
|
||||
{
|
||||
SAMPLE_TYPE_INFO *iter = sample_type_list, *next;
|
||||
|
||||
while (iter) {
|
||||
next = iter->next;
|
||||
_AL_FREE(iter->ext);
|
||||
_AL_FREE(iter);
|
||||
iter = next;
|
||||
}
|
||||
|
||||
sample_type_list = NULL;
|
||||
|
||||
/* If we are using a destructor, then we only want to prune the list
|
||||
* down to valid modules. So we clean up as usual, but then reinstall
|
||||
* the internal modules.
|
||||
*/
|
||||
#ifdef ALLEGRO_USE_CONSTRUCTOR
|
||||
_register_sample_file_type_init();
|
||||
#endif
|
||||
|
||||
_remove_exit_func(register_sample_file_type_exit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _register_sample_file_type_init:
|
||||
* Register built-in sample file types.
|
||||
*/
|
||||
void _register_sample_file_type_init(void)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
_add_exit_func(register_sample_file_type_exit,
|
||||
"register_sample_file_type_exit");
|
||||
|
||||
register_sample_file_type(uconvert_ascii("wav", buf), load_wav, NULL);
|
||||
register_sample_file_type(uconvert_ascii("voc", buf), load_voc, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ALLEGRO_USE_CONSTRUCTOR
|
||||
CONSTRUCTOR_FUNCTION(static void sample_filetype_constructor(void));
|
||||
DESTRUCTOR_FUNCTION(static void sample_filetype_destructor(void));
|
||||
|
||||
/* sample_filetype_constructor:
|
||||
* Register sample filetype functions if this object file is linked
|
||||
* in. This isn't called if the load_sample() and save_sample()
|
||||
* functions aren't used in a program, thus saving a little space
|
||||
* in statically linked programs.
|
||||
*/
|
||||
static void sample_filetype_constructor(void)
|
||||
{
|
||||
_register_sample_file_type_init();
|
||||
}
|
||||
|
||||
/* sample_filetype_destructor:
|
||||
* Since we only want to destroy the whole list when we *actually*
|
||||
* quit, not just when allegro_exit() is called, we need to use a
|
||||
* destructor to accomplish this.
|
||||
*/
|
||||
static void sample_filetype_destructor(void)
|
||||
{
|
||||
SAMPLE_TYPE_INFO *iter = sample_type_list, *next;
|
||||
|
||||
while (iter) {
|
||||
next = iter->next;
|
||||
_AL_FREE(iter->ext);
|
||||
_AL_FREE(iter);
|
||||
iter = next;
|
||||
}
|
||||
|
||||
sample_type_list = NULL;
|
||||
|
||||
_remove_exit_func(register_sample_file_type_exit);
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,196 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* Audio stream functions.
|
||||
*
|
||||
* By Shawn Hargreaves (original version by Andrew Ellem).
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#include "allegro.h"
|
||||
#include "allegro/internal/aintern.h"
|
||||
|
||||
|
||||
|
||||
/* play_audio_stream:
|
||||
* Creates a new audio stream and starts it playing. The length is the
|
||||
* size of each transfer buffer.
|
||||
*/
|
||||
AUDIOSTREAM *play_audio_stream(int len, int bits, int stereo, int freq, int vol, int pan)
|
||||
{
|
||||
AUDIOSTREAM *stream;
|
||||
int i, bufcount;
|
||||
ASSERT(len > 0);
|
||||
ASSERT(bits > 0);
|
||||
ASSERT(freq > 0);
|
||||
|
||||
/* decide how many buffer fragments we will need */
|
||||
if ((digi_driver) && (digi_driver->buffer_size))
|
||||
i = digi_driver->buffer_size();
|
||||
else
|
||||
i = 2048;
|
||||
|
||||
if (len >= i)
|
||||
bufcount = 1;
|
||||
else
|
||||
bufcount = (i + len-1) / len;
|
||||
|
||||
/* create the stream structure */
|
||||
stream = _AL_MALLOC(sizeof(AUDIOSTREAM));
|
||||
if (!stream)
|
||||
return NULL;
|
||||
|
||||
stream->len = len;
|
||||
stream->bufcount = bufcount;
|
||||
stream->bufnum = 0;
|
||||
stream->active = 1;
|
||||
stream->locked = NULL;
|
||||
|
||||
/* create the underlying sample */
|
||||
stream->samp = create_sample(bits, stereo, freq, len*bufcount*2);
|
||||
if (!stream->samp) {
|
||||
_AL_FREE(stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fill with silence */
|
||||
if (bits == 16) {
|
||||
unsigned short *p = stream->samp->data;
|
||||
for (i=0; i < len*bufcount*2 * ((stereo) ? 2 : 1); i++)
|
||||
p[i] = 0x8000;
|
||||
}
|
||||
else {
|
||||
unsigned char *p = stream->samp->data;
|
||||
for (i=0; i < len*bufcount*2 * ((stereo) ? 2 : 1); i++)
|
||||
p[i] = 0x80;
|
||||
}
|
||||
|
||||
LOCK_DATA(stream, sizeof(AUDIOSTREAM));
|
||||
|
||||
/* play the sample in looped mode */
|
||||
stream->voice = allocate_voice(stream->samp);
|
||||
if (stream->voice < 0) {
|
||||
destroy_sample(stream->samp);
|
||||
UNLOCK_DATA(stream, sizeof(AUDIOSTREAM));
|
||||
_AL_FREE(stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
voice_set_playmode(stream->voice, PLAYMODE_LOOP);
|
||||
voice_set_volume(stream->voice, vol);
|
||||
voice_set_pan(stream->voice, pan);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* stop_audio_stream:
|
||||
* Destroys an audio stream when it is no longer required.
|
||||
*/
|
||||
void stop_audio_stream(AUDIOSTREAM *stream)
|
||||
{
|
||||
ASSERT(stream);
|
||||
|
||||
if ((stream->locked) && (digi_driver->unlock_voice))
|
||||
digi_driver->unlock_voice(stream->voice);
|
||||
|
||||
voice_stop(stream->voice);
|
||||
deallocate_voice(stream->voice);
|
||||
|
||||
destroy_sample(stream->samp);
|
||||
|
||||
UNLOCK_DATA(stream, sizeof(AUDIOSTREAM));
|
||||
_AL_FREE(stream);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* get_audio_stream_buffer:
|
||||
* Returns a pointer to the next audio buffer, or NULL if the previous
|
||||
* data is still playing. This must be called at regular intervals while
|
||||
* the stream is playing, and you must fill the return address with the
|
||||
* appropriate number (the same length that you specified when you create
|
||||
* the stream) of samples. Call free_audio_stream_buffer() after loading
|
||||
* the new samples, to indicate that the data is now valid.
|
||||
*/
|
||||
void *get_audio_stream_buffer(AUDIOSTREAM *stream)
|
||||
{
|
||||
int pos;
|
||||
char *data = NULL;
|
||||
ASSERT(stream);
|
||||
|
||||
if (stream->bufnum == stream->active * stream->bufcount) {
|
||||
/* waiting for the sample to switch halves */
|
||||
pos = voice_get_position(stream->voice);
|
||||
|
||||
if (stream->active == 0) {
|
||||
if (pos < stream->len*stream->bufcount)
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
if (pos >= stream->len*stream->bufcount)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stream->active = 1-stream->active;
|
||||
}
|
||||
|
||||
/* make sure we got access to the right bit of sample data */
|
||||
if (!stream->locked) {
|
||||
pos = (1-stream->active) * stream->bufcount * stream->len;
|
||||
|
||||
if (digi_driver->lock_voice)
|
||||
data = digi_driver->lock_voice(stream->voice, pos, pos+stream->bufcount*stream->len);
|
||||
|
||||
if (data)
|
||||
stream->locked = data;
|
||||
else
|
||||
stream->locked = (char *)stream->samp->data + (pos * ((stream->samp->bits==8) ? 1 : sizeof(short)) * ((stream->samp->stereo) ? 2 : 1));
|
||||
}
|
||||
|
||||
return (char *)stream->locked + ((stream->bufnum % stream->bufcount) *
|
||||
stream->len *
|
||||
((stream->samp->bits==8) ? 1 : sizeof(short)) *
|
||||
((stream->samp->stereo) ? 2 : 1));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* free_audio_stream_buffer:
|
||||
* Indicates that a sample buffer previously returned by a call to
|
||||
* get_audio_stream_buffer() has now been filled with valid data.
|
||||
*/
|
||||
void free_audio_stream_buffer(AUDIOSTREAM *stream)
|
||||
{
|
||||
ASSERT(stream);
|
||||
|
||||
/* flip buffers */
|
||||
stream->bufnum++;
|
||||
|
||||
if (stream->bufnum >= stream->bufcount*2)
|
||||
stream->bufnum = 0;
|
||||
|
||||
/* unlock old waveform region */
|
||||
if ((stream->locked) &&
|
||||
((stream->bufnum == 0) || (stream->bufnum == stream->bufcount))) {
|
||||
|
||||
if (digi_driver->unlock_voice)
|
||||
digi_driver->unlock_voice(stream->voice);
|
||||
|
||||
stream->locked = NULL;
|
||||
}
|
||||
|
||||
/* start playing if it wasn't already */
|
||||
if (voice_get_position(stream->voice) == -1)
|
||||
voice_start(stream->voice);
|
||||
}
|
@ -1,409 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* ALSA 0.5 sound driver.
|
||||
*
|
||||
* By Peter Wang (based heavily on uoss.c)
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#include "allegro.h"
|
||||
|
||||
#if (ALLEGRO_ALSA_VERSION == 5) && (defined ALLEGRO_WITH_ALSADIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))
|
||||
|
||||
#include "allegro/internal/aintern.h"
|
||||
#ifdef ALLEGRO_QNX
|
||||
#include "allegro/platform/aintqnx.h"
|
||||
#else
|
||||
#include "allegro/platform/aintunix.h"
|
||||
#endif
|
||||
|
||||
#ifndef SCAN_DEPEND
|
||||
#include <string.h>
|
||||
#include <sys/asoundlib.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SND_PCM_SFMT_S16_NE
|
||||
#ifdef ALLEGRO_BIG_ENDIAN
|
||||
#define SND_PCM_SFMT_S16_NE SND_PCM_SFMT_S16_BE
|
||||
#else
|
||||
#define SND_PCM_SFMT_S16_NE SND_PCM_SFMT_S16_LE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SND_PCM_SFMT_U16_NE
|
||||
#ifdef ALLEGRO_BIG_ENDIAN
|
||||
#define SND_PCM_SFMT_U16_NE SND_PCM_SFMT_U16_BE
|
||||
#else
|
||||
#define SND_PCM_SFMT_U16_NE SND_PCM_SFMT_U16_LE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#define ALSA_DEFAULT_NUMFRAGS 16
|
||||
|
||||
|
||||
static snd_pcm_t *pcm_handle;
|
||||
static int alsa_bufsize;
|
||||
static unsigned char *alsa_bufdata;
|
||||
static int alsa_bits, alsa_signed, alsa_rate, alsa_stereo;
|
||||
static int alsa_fragments;
|
||||
|
||||
static char alsa_desc[256] = EMPTY_STRING;
|
||||
|
||||
|
||||
|
||||
static int alsa_detect(int input);
|
||||
static int alsa_init(int input, int voices);
|
||||
static void alsa_exit(int input);
|
||||
static int alsa_set_mixer_volume(int volume);
|
||||
static int alsa_buffer_size(void);
|
||||
|
||||
|
||||
|
||||
DIGI_DRIVER digi_alsa =
|
||||
{
|
||||
DIGI_ALSA,
|
||||
empty_string,
|
||||
empty_string,
|
||||
"ALSA",
|
||||
0,
|
||||
0,
|
||||
MIXER_MAX_SFX,
|
||||
MIXER_DEF_SFX,
|
||||
|
||||
alsa_detect,
|
||||
alsa_init,
|
||||
alsa_exit,
|
||||
alsa_set_mixer_volume,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
alsa_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
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* alsa_buffer_size:
|
||||
* Returns the current DMA buffer size, for use by the audiostream code.
|
||||
*/
|
||||
static int alsa_buffer_size(void)
|
||||
{
|
||||
return alsa_bufsize * alsa_fragments / (alsa_bits / 8) / (alsa_stereo ? 2 : 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_update:
|
||||
* Update data.
|
||||
*/
|
||||
static void alsa_update(int threaded)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < alsa_fragments; i++) {
|
||||
if (snd_pcm_write(pcm_handle, alsa_bufdata, alsa_bufsize) != alsa_bufsize)
|
||||
break;
|
||||
_mix_some_samples((uintptr_t) alsa_bufdata, 0, alsa_signed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_detect:
|
||||
* Detect driver presence.
|
||||
*/
|
||||
static int alsa_detect(int input)
|
||||
{
|
||||
snd_pcm_t *handle;
|
||||
snd_pcm_info_t info;
|
||||
int card, device;
|
||||
char tmp1[128], tmp2[128];
|
||||
int ret = FALSE;
|
||||
|
||||
card = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_card", tmp2),
|
||||
snd_defaults_card());
|
||||
|
||||
device = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_pcmdevice", tmp2),
|
||||
snd_defaults_pcm_device());
|
||||
|
||||
if (snd_pcm_open(&handle, card, device, (SND_PCM_OPEN_PLAYBACK
|
||||
| SND_PCM_OPEN_NONBLOCK)) == 0) {
|
||||
if ((snd_pcm_info(handle, &info) == 0)
|
||||
&& (info.flags & SND_PCM_INFO_PLAYBACK))
|
||||
ret = TRUE;
|
||||
|
||||
snd_pcm_close(handle);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_init:
|
||||
* ALSA init routine.
|
||||
*/
|
||||
static int alsa_init(int input, int voices)
|
||||
{
|
||||
int card, device;
|
||||
int format, bps, fragsize, numfrags;
|
||||
snd_pcm_channel_params_t params;
|
||||
snd_pcm_channel_setup_t setup;
|
||||
char tmp1[128], tmp2[128];
|
||||
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Load config. */
|
||||
card = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_card", tmp2),
|
||||
snd_defaults_card());
|
||||
|
||||
device = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_pcmdevice", tmp2),
|
||||
snd_defaults_pcm_device());
|
||||
|
||||
fragsize = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_fragsize", tmp2),
|
||||
-1);
|
||||
|
||||
numfrags = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_numfrags", tmp2),
|
||||
ALSA_DEFAULT_NUMFRAGS);
|
||||
|
||||
/* Open PCM device. */
|
||||
if (snd_pcm_open(&pcm_handle, card, device, (SND_PCM_OPEN_PLAYBACK
|
||||
| SND_PCM_OPEN_NONBLOCK)) < 0) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open card/pcm device"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Set format variables. */
|
||||
alsa_bits = (_sound_bits == 8) ? 8 : 16;
|
||||
alsa_stereo = (_sound_stereo) ? 1 : 0;
|
||||
alsa_rate = (_sound_freq > 0) ? _sound_freq : 44100;
|
||||
|
||||
format = ((alsa_bits == 16) ? SND_PCM_SFMT_S16_NE : SND_PCM_SFMT_U8);
|
||||
|
||||
alsa_signed = 0;
|
||||
bps = alsa_rate * (alsa_stereo ? 2 : 1);
|
||||
switch (format) {
|
||||
case SND_PCM_SFMT_S8:
|
||||
alsa_signed = 1;
|
||||
case SND_PCM_SFMT_U8:
|
||||
alsa_bits = 8;
|
||||
break;
|
||||
case SND_PCM_SFMT_S16_NE:
|
||||
alsa_signed = 1;
|
||||
case SND_PCM_SFMT_U16_NE:
|
||||
alsa_bits = 16;
|
||||
bps <<= 1;
|
||||
if (sizeof(short) != 2) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (fragsize < 0) {
|
||||
bps >>= 9;
|
||||
if (bps < 16)
|
||||
bps = 16;
|
||||
fragsize = 1;
|
||||
while ((fragsize << 1) < bps)
|
||||
fragsize <<= 1;
|
||||
}
|
||||
else {
|
||||
fragsize = fragsize * (alsa_bits / 8) * (alsa_stereo ? 2 : 1);
|
||||
}
|
||||
|
||||
/* Set PCM channel format. */
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
params.mode = SND_PCM_MODE_BLOCK;
|
||||
params.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
params.start_mode = SND_PCM_START_FULL;
|
||||
params.stop_mode = SND_PCM_STOP_ROLLOVER;
|
||||
params.format.interleave = 1;
|
||||
params.format.format = format;
|
||||
params.format.rate = alsa_rate;
|
||||
params.format.voices = alsa_stereo + 1;
|
||||
params.buf.block.frag_size = fragsize;
|
||||
params.buf.block.frags_min = 1;
|
||||
params.buf.block.frags_max = numfrags;
|
||||
|
||||
if (snd_pcm_channel_params(pcm_handle, ¶ms) < 0) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not set channel parameters"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
snd_pcm_channel_prepare(pcm_handle, SND_PCM_CHANNEL_PLAYBACK);
|
||||
|
||||
/* Read back fragments information. */
|
||||
memset(&setup, 0, sizeof(setup));
|
||||
setup.mode = SND_PCM_MODE_BLOCK;
|
||||
setup.channel = SND_PCM_CHANNEL_PLAYBACK;
|
||||
|
||||
if (snd_pcm_channel_setup(pcm_handle, &setup) < 0) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not get channel setup"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
alsa_fragments = numfrags;
|
||||
alsa_bufsize = setup.buf.block.frag_size;
|
||||
|
||||
/* Allocate mixing buffer. */
|
||||
alsa_bufdata = _AL_MALLOC_ATOMIC(alsa_bufsize);
|
||||
if (!alsa_bufdata) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Initialise mixer. */
|
||||
digi_alsa.voices = voices;
|
||||
|
||||
if (_mixer_init(alsa_bufsize / (alsa_bits / 8), alsa_rate,
|
||||
alsa_stereo, ((alsa_bits == 16) ? 1 : 0),
|
||||
&digi_alsa.voices) != 0) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
_mix_some_samples((uintptr_t) alsa_bufdata, 0, alsa_signed);
|
||||
|
||||
/* Add audio interrupt. */
|
||||
_unix_bg_man->register_func(alsa_update);
|
||||
|
||||
uszprintf(alsa_desc, sizeof(alsa_desc),
|
||||
get_config_text("Alsa 0.5, Card #%d, device #%d: %d bits, %s, %d bps, %s"),
|
||||
card, device, alsa_bits,
|
||||
uconvert_ascii((alsa_signed ? "signed" : "unsigned"), tmp1),
|
||||
alsa_rate,
|
||||
uconvert_ascii((alsa_stereo ? "stereo" : "mono"), tmp2));
|
||||
|
||||
digi_driver->desc = alsa_desc;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
||||
if (pcm_handle) {
|
||||
snd_pcm_close(pcm_handle);
|
||||
pcm_handle = NULL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_exit:
|
||||
* Shutdown ALSA driver.
|
||||
*/
|
||||
static void alsa_exit(int input)
|
||||
{
|
||||
if (input) {
|
||||
return;
|
||||
}
|
||||
|
||||
_unix_bg_man->unregister_func(alsa_update);
|
||||
|
||||
_AL_FREE(alsa_bufdata);
|
||||
alsa_bufdata = NULL;
|
||||
|
||||
_mixer_exit();
|
||||
|
||||
snd_pcm_close(pcm_handle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_set_mixer_volume:
|
||||
* Set mixer volume (0-255)
|
||||
*/
|
||||
static int alsa_set_mixer_volume(int volume)
|
||||
{
|
||||
/* TODO */
|
||||
#if 0
|
||||
snd_mixer_t *handle;
|
||||
int card, device;
|
||||
|
||||
if (snd_mixer_open(&handle, card, device) == 0) {
|
||||
/* do something special */
|
||||
snd_mixer_close(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ALLEGRO_MODULE
|
||||
|
||||
/* _module_init:
|
||||
* Called when loaded as a dynamically linked module.
|
||||
*/
|
||||
void _module_init(int system_driver)
|
||||
{
|
||||
_unix_register_digi_driver(DIGI_ALSA, &digi_alsa, TRUE, TRUE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,561 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* ALSA 0.9 sound driver.
|
||||
*
|
||||
* By Thomas Fjellstrom.
|
||||
*
|
||||
* Extensively modified by Elias Pschernig.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#include "allegro.h"
|
||||
|
||||
#if (ALLEGRO_ALSA_VERSION == 9) && (defined ALLEGRO_WITH_ALSADIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))
|
||||
|
||||
#include "allegro/internal/aintern.h"
|
||||
#ifdef ALLEGRO_QNX
|
||||
#include "allegro/platform/aintqnx.h"
|
||||
#else
|
||||
#include "allegro/platform/aintunix.h"
|
||||
#endif
|
||||
|
||||
#ifndef SCAN_DEPEND
|
||||
#include <string.h>
|
||||
#define ALSA_PCM_NEW_HW_PARAMS_API 1
|
||||
#include <alsa/asoundlib.h>
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef SND_PCM_FORMAT_S16_NE
|
||||
#ifdef ALLEGRO_BIG_ENDIAN
|
||||
#define SND_PCM_FORMAT_S16_NE SND_PCM_FORMAT_S16_BE
|
||||
#else
|
||||
#define SND_PCM_FORMAT_S16_NE SND_PCM_FORMAT_S16_LE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef SND_PCM_FORMAT_U16_NE
|
||||
#ifdef ALLEGRO_BIG_ENDIAN
|
||||
#define SND_PCM_FORMAT_U16_NE SND_PCM_FORMAT_U16_BE
|
||||
#else
|
||||
#define SND_PCM_FORMAT_U16_NE SND_PCM_FORMAT_U16_LE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define ALSA9_CHECK(a) do { \
|
||||
int err = (a); \
|
||||
if (err<0) { \
|
||||
uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, "ALSA: %s : %s", #a, get_config_text(snd_strerror(err))); \
|
||||
goto Error; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define PREFIX_I "al-alsa9 INFO: "
|
||||
#define PREFIX_W "al-alsa9 WARNING: "
|
||||
#define PREFIX_E "al-alsa9 ERROR: "
|
||||
|
||||
static char const *alsa_device = "default";
|
||||
static char const *alsa_mixer_device = "default";
|
||||
static snd_pcm_hw_params_t *hwparams = NULL;
|
||||
static snd_pcm_sw_params_t *swparams = NULL;
|
||||
static snd_output_t *snd_output = NULL;
|
||||
static snd_pcm_uframes_t alsa_bufsize;
|
||||
static snd_mixer_t *alsa_mixer = NULL;
|
||||
static snd_mixer_elem_t *alsa_mixer_elem = NULL;
|
||||
static long alsa_mixer_elem_min, alsa_mixer_elem_max;
|
||||
static double alsa_mixer_allegro_ratio = 0.0;
|
||||
|
||||
#define ALSA_DEFAULT_BUFFER_MS 100
|
||||
#define ALSA_DEFAULT_NUMFRAGS 5
|
||||
|
||||
static snd_pcm_t *pcm_handle;
|
||||
static unsigned char *alsa_bufdata;
|
||||
static int alsa_bits, alsa_signed, alsa_stereo;
|
||||
static unsigned int alsa_rate;
|
||||
static unsigned int alsa_fragments;
|
||||
static int alsa_sample_size;
|
||||
|
||||
static struct pollfd *ufds = NULL;
|
||||
static int pdc = 0;
|
||||
static int poll_next;
|
||||
|
||||
static char alsa_desc[256] = EMPTY_STRING;
|
||||
|
||||
static int alsa_detect(int input);
|
||||
static int alsa_init(int input, int voices);
|
||||
static void alsa_exit(int input);
|
||||
static int alsa_set_mixer_volume(int volume);
|
||||
static int alsa_get_mixer_volume(void);
|
||||
static int alsa_buffer_size(void);
|
||||
|
||||
|
||||
|
||||
DIGI_DRIVER digi_alsa =
|
||||
{
|
||||
DIGI_ALSA,
|
||||
empty_string,
|
||||
empty_string,
|
||||
"ALSA",
|
||||
0,
|
||||
0,
|
||||
MIXER_MAX_SFX,
|
||||
MIXER_DEF_SFX,
|
||||
|
||||
alsa_detect,
|
||||
alsa_init,
|
||||
alsa_exit,
|
||||
alsa_set_mixer_volume,
|
||||
alsa_get_mixer_volume,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
alsa_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
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* alsa_buffer_size:
|
||||
* Returns the current DMA buffer size, for use by the audiostream code.
|
||||
*/
|
||||
static int alsa_buffer_size(void)
|
||||
{
|
||||
return alsa_bufsize;
|
||||
}
|
||||
|
||||
/* xrun_recovery:
|
||||
* Underrun and suspend recovery
|
||||
*/
|
||||
static int xrun_recovery(snd_pcm_t *handle, int err)
|
||||
{
|
||||
if (err == -EPIPE) { /* under-run */
|
||||
err = snd_pcm_prepare(pcm_handle);
|
||||
if (err < 0)
|
||||
fprintf(stderr, "Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
|
||||
return 0;
|
||||
}
|
||||
/* TODO: Can't wait here like that - we are inside an 'interrupt' after all. */
|
||||
#if 0
|
||||
else if (err == -ESTRPIPE) {
|
||||
while ((err = snd_pcm_resume(pcm_handle)) == -EAGAIN)
|
||||
sleep(1); /* wait until the suspend flag is released */
|
||||
|
||||
if (err < 0) {
|
||||
err = snd_pcm_prepare(pcm_handle);
|
||||
if (err < 0)
|
||||
fprintf(stderr, "Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_mix
|
||||
* Mix and send some samples to ALSA.
|
||||
*/
|
||||
static void alsa_mix(void)
|
||||
{
|
||||
int ret, samples = alsa_bufsize;
|
||||
unsigned char *ptr = alsa_bufdata;
|
||||
|
||||
while (samples > 0) {
|
||||
ret = snd_pcm_writei(pcm_handle, ptr, samples);
|
||||
if (ret == -EAGAIN)
|
||||
continue;
|
||||
|
||||
if (ret < 0) {
|
||||
if (xrun_recovery(pcm_handle, ret) < 0)
|
||||
fprintf(stderr, "Write error: %s\n", snd_strerror(ret));
|
||||
poll_next = 0;
|
||||
break; /* skip one period */
|
||||
}
|
||||
if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_RUNNING)
|
||||
poll_next = 1;
|
||||
samples -= ret;
|
||||
ptr += ret * alsa_sample_size;
|
||||
}
|
||||
|
||||
_mix_some_samples((uintptr_t)alsa_bufdata, 0, alsa_signed);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_update:
|
||||
* Updates main buffer in case ALSA is ready.
|
||||
*/
|
||||
static void alsa_update(int threaded)
|
||||
{
|
||||
unsigned short revents;
|
||||
|
||||
if (poll_next) {
|
||||
poll(ufds, pdc, 0);
|
||||
snd_pcm_poll_descriptors_revents(pcm_handle, ufds, pdc, &revents);
|
||||
if (revents & POLLERR) {
|
||||
if (snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN ||
|
||||
snd_pcm_state(pcm_handle) == SND_PCM_STATE_SUSPENDED) {
|
||||
int err = snd_pcm_state(pcm_handle) == SND_PCM_STATE_XRUN ? -EPIPE : -ESTRPIPE;
|
||||
if (xrun_recovery(pcm_handle, err) < 0) {
|
||||
fprintf(stderr, "Write error: %s\n", snd_strerror(err));
|
||||
}
|
||||
poll_next = 0;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Wait for poll failed\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!(revents & POLLOUT))
|
||||
return;
|
||||
}
|
||||
alsa_mix();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_detect:
|
||||
* Detects driver presence.
|
||||
*/
|
||||
static int alsa_detect(int input)
|
||||
{
|
||||
int ret = FALSE;
|
||||
char tmp1[128], tmp2[128];
|
||||
|
||||
alsa_device = get_config_string(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_device", tmp2),
|
||||
alsa_device);
|
||||
|
||||
ret = snd_pcm_open(&pcm_handle, alsa_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
||||
if (ret < 0) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open card/pcm device"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
snd_pcm_close(pcm_handle);
|
||||
pcm_handle = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_init:
|
||||
* ALSA init routine.
|
||||
*/
|
||||
static int alsa_init(int input, int voices)
|
||||
{
|
||||
int ret = 0;
|
||||
char tmp1[128], tmp2[128];
|
||||
int format = 0;
|
||||
unsigned int numfrags = 0;
|
||||
snd_pcm_uframes_t fragsize;
|
||||
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ALSA9_CHECK(snd_output_stdio_attach(&snd_output, stdout, 0));
|
||||
|
||||
alsa_device = get_config_string(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_device", tmp2),
|
||||
alsa_device);
|
||||
|
||||
alsa_mixer_device = get_config_string(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_mixer_device", tmp2),
|
||||
alsa_mixer_device);
|
||||
|
||||
fragsize = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_fragsize", tmp2), 0);
|
||||
|
||||
numfrags = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_numfrags", tmp2),
|
||||
ALSA_DEFAULT_NUMFRAGS);
|
||||
|
||||
ret = snd_pcm_open(&pcm_handle, alsa_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
||||
if (ret < 0) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open card/pcm device"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
snd_mixer_open(&alsa_mixer, 0);
|
||||
|
||||
if (alsa_mixer
|
||||
&& snd_mixer_attach(alsa_mixer, alsa_mixer_device) >= 0
|
||||
&& snd_mixer_selem_register (alsa_mixer, NULL, NULL) >= 0
|
||||
&& snd_mixer_load(alsa_mixer) >= 0) {
|
||||
const char *alsa_mixer_elem_name = get_config_string(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_mixer_elem", tmp2),
|
||||
"PCM");
|
||||
|
||||
alsa_mixer_elem = snd_mixer_first_elem(alsa_mixer);
|
||||
|
||||
while (alsa_mixer_elem) {
|
||||
const char *name = snd_mixer_selem_get_name(alsa_mixer_elem);
|
||||
|
||||
if (strcasecmp(name, alsa_mixer_elem_name) == 0) {
|
||||
snd_mixer_selem_get_playback_volume_range(alsa_mixer_elem, &alsa_mixer_elem_min, &alsa_mixer_elem_max);
|
||||
alsa_mixer_allegro_ratio = (double) (alsa_mixer_elem_max - alsa_mixer_elem_min) / (double) 255;
|
||||
break;
|
||||
}
|
||||
|
||||
alsa_mixer_elem = snd_mixer_elem_next(alsa_mixer_elem);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set format variables. */
|
||||
alsa_bits = (_sound_bits == 8) ? 8 : 16;
|
||||
alsa_stereo = (_sound_stereo) ? 1 : 0;
|
||||
alsa_rate = (_sound_freq > 0) ? _sound_freq : 44100;
|
||||
|
||||
snd_pcm_hw_params_malloc(&hwparams);
|
||||
ALSA9_CHECK(snd_pcm_hw_params_any(pcm_handle, hwparams));
|
||||
|
||||
if (alsa_bits == 8) {
|
||||
if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_U8) == 0) {
|
||||
format = SND_PCM_FORMAT_U8;
|
||||
alsa_signed = 0;
|
||||
}
|
||||
else if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S8) == 0) {
|
||||
format = SND_PCM_FORMAT_S8;
|
||||
alsa_signed = 1;
|
||||
}
|
||||
else {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
else if (alsa_bits == 16) {
|
||||
if (sizeof(short) != 2) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
|
||||
goto Error;
|
||||
}
|
||||
|
||||
if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_U16_NE) == 0) {
|
||||
format = SND_PCM_FORMAT_U16_NE;
|
||||
alsa_signed = 0;
|
||||
}
|
||||
else if (snd_pcm_hw_params_test_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_NE) == 0) {
|
||||
format = SND_PCM_FORMAT_S16_NE;
|
||||
alsa_signed = 1;
|
||||
}
|
||||
else {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
|
||||
alsa_sample_size = (alsa_bits / 8) * (alsa_stereo ? 2 : 1);
|
||||
|
||||
if (fragsize == 0) {
|
||||
unsigned int size = alsa_rate * ALSA_DEFAULT_BUFFER_MS / 1000 / numfrags;
|
||||
fragsize = 1;
|
||||
while (fragsize < size)
|
||||
fragsize <<= 1;
|
||||
}
|
||||
|
||||
ALSA9_CHECK(snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED));
|
||||
ALSA9_CHECK(snd_pcm_hw_params_set_format(pcm_handle, hwparams, format));
|
||||
ALSA9_CHECK(snd_pcm_hw_params_set_channels(pcm_handle, hwparams, alsa_stereo + 1));
|
||||
|
||||
ALSA9_CHECK(snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &alsa_rate, NULL));
|
||||
ALSA9_CHECK(snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &fragsize, NULL));
|
||||
ALSA9_CHECK(snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &numfrags, NULL));
|
||||
|
||||
ALSA9_CHECK(snd_pcm_hw_params(pcm_handle, hwparams));
|
||||
|
||||
ALSA9_CHECK(snd_pcm_hw_params_get_period_size(hwparams, &alsa_bufsize, NULL));
|
||||
ALSA9_CHECK(snd_pcm_hw_params_get_periods(hwparams, &alsa_fragments, NULL));
|
||||
|
||||
TRACE (PREFIX_I "alsa_bufsize = %ld, alsa_fragments = %d\n", alsa_bufsize, alsa_fragments);
|
||||
|
||||
snd_pcm_sw_params_malloc(&swparams);
|
||||
ALSA9_CHECK(snd_pcm_sw_params_current(pcm_handle, swparams));
|
||||
ALSA9_CHECK(snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, alsa_bufsize));
|
||||
ALSA9_CHECK(snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, fragsize));
|
||||
ALSA9_CHECK(snd_pcm_sw_params(pcm_handle, swparams));
|
||||
|
||||
/* Allocate mixing buffer. */
|
||||
alsa_bufdata = _AL_MALLOC_ATOMIC(alsa_bufsize * alsa_sample_size);
|
||||
if (!alsa_bufdata) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer"));
|
||||
goto Error;
|
||||
}
|
||||
|
||||
/* Initialise mixer. */
|
||||
digi_alsa.voices = voices;
|
||||
|
||||
if (_mixer_init(alsa_bufsize * (alsa_stereo ? 2 : 1), alsa_rate,
|
||||
alsa_stereo, ((alsa_bits == 16) ? 1 : 0),
|
||||
&digi_alsa.voices) != 0) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer"));
|
||||
goto Error;
|
||||
}
|
||||
|
||||
snd_pcm_prepare(pcm_handle);
|
||||
pdc = snd_pcm_poll_descriptors_count (pcm_handle);
|
||||
if (pdc <= 0) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Invalid poll descriptors count"));
|
||||
goto Error;
|
||||
}
|
||||
|
||||
ufds = _AL_MALLOC(sizeof(struct pollfd) * pdc);
|
||||
if (ufds == NULL) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not enough memory for poll descriptors"));
|
||||
goto Error;
|
||||
}
|
||||
ALSA9_CHECK(snd_pcm_poll_descriptors(pcm_handle, ufds, pdc));
|
||||
|
||||
poll_next = 0;
|
||||
|
||||
_mix_some_samples((uintptr_t) alsa_bufdata, 0, alsa_signed);
|
||||
|
||||
/* Add audio interrupt. */
|
||||
_unix_bg_man->register_func(alsa_update);
|
||||
|
||||
uszprintf(alsa_desc, sizeof(alsa_desc),
|
||||
get_config_text
|
||||
("Alsa 0.9, Device '%s': %d bits, %s, %d bps, %s"),
|
||||
alsa_device, alsa_bits,
|
||||
uconvert_ascii((alsa_signed ? "signed" : "unsigned"), tmp1),
|
||||
alsa_rate, uconvert_ascii((alsa_stereo ? "stereo" : "mono"), tmp2));
|
||||
|
||||
digi_driver->desc = alsa_desc;
|
||||
return 0;
|
||||
|
||||
Error:
|
||||
if (pcm_handle) {
|
||||
snd_pcm_close(pcm_handle);
|
||||
pcm_handle = NULL;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_exit:
|
||||
* Shuts down ALSA driver.
|
||||
*/
|
||||
static void alsa_exit(int input)
|
||||
{
|
||||
if (input)
|
||||
return;
|
||||
|
||||
_unix_bg_man->unregister_func(alsa_update);
|
||||
|
||||
_AL_FREE(alsa_bufdata);
|
||||
alsa_bufdata = NULL;
|
||||
|
||||
_mixer_exit();
|
||||
|
||||
if (alsa_mixer)
|
||||
snd_mixer_close(alsa_mixer);
|
||||
|
||||
snd_pcm_close(pcm_handle);
|
||||
|
||||
snd_pcm_hw_params_free(hwparams);
|
||||
snd_pcm_sw_params_free(swparams);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_set_mixer_volume:
|
||||
* Set mixer volume (0-255)
|
||||
*/
|
||||
static int alsa_set_mixer_volume(int volume)
|
||||
{
|
||||
if (alsa_mixer && alsa_mixer_elem) {
|
||||
snd_mixer_selem_set_playback_volume(alsa_mixer_elem, 0, volume * alsa_mixer_allegro_ratio);
|
||||
snd_mixer_selem_set_playback_volume(alsa_mixer_elem, 1, volume * alsa_mixer_allegro_ratio);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_get_mixer_volume:
|
||||
* Return mixer volume (0-255)
|
||||
*/
|
||||
static int alsa_get_mixer_volume(void)
|
||||
{
|
||||
if (alsa_mixer && alsa_mixer_elem) {
|
||||
long vol1, vol2;
|
||||
|
||||
snd_mixer_handle_events(alsa_mixer);
|
||||
|
||||
if (snd_mixer_selem_get_playback_volume(alsa_mixer_elem, 0, &vol1) < 0)
|
||||
return -1;
|
||||
if (snd_mixer_selem_get_playback_volume(alsa_mixer_elem, 1, &vol2) < 0)
|
||||
return -1;
|
||||
|
||||
vol1 /= alsa_mixer_allegro_ratio;
|
||||
vol2 /= alsa_mixer_allegro_ratio;
|
||||
|
||||
return (vol1 + vol2) / 2;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ALLEGRO_MODULE
|
||||
|
||||
/* _module_init:
|
||||
* Called when loaded as a dynamically linked module.
|
||||
*/
|
||||
void _module_init(int system_driver)
|
||||
{
|
||||
_unix_register_digi_driver(DIGI_ALSA, &digi_alsa, TRUE, TRUE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,266 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* ALSA RawMIDI Sound driver.
|
||||
*
|
||||
* By Thomas Fjellstrom.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
#include "allegro.h"
|
||||
|
||||
#if (defined ALLEGRO_WITH_ALSAMIDI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))
|
||||
|
||||
#include "allegro/internal/aintern.h"
|
||||
|
||||
#ifdef ALLEGRO_QNX
|
||||
#include "allegro/platform/aintqnx.h"
|
||||
#else
|
||||
#include "allegro/platform/aintunix.h"
|
||||
#endif
|
||||
|
||||
#ifndef SCAN_DEPEND
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if ALLEGRO_ALSA_VERSION == 9
|
||||
#define ALSA_PCM_NEW_HW_PARAMS_API 1
|
||||
#include <alsa/asoundlib.h>
|
||||
#else /* ALLEGRO_ALSA_VERSION == 5 */
|
||||
#include <sys/asoundlib.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define ALSA_RAWMIDI_MAX_ERRORS 3
|
||||
|
||||
|
||||
static int alsa_rawmidi_detect(int input);
|
||||
static int alsa_rawmidi_init(int input, int voices);
|
||||
static void alsa_rawmidi_exit(int input);
|
||||
static void alsa_rawmidi_output(int data);
|
||||
|
||||
static char alsa_rawmidi_desc[256];
|
||||
|
||||
static snd_rawmidi_t *rawmidi_handle = NULL;
|
||||
static int alsa_rawmidi_errors = 0;
|
||||
|
||||
|
||||
MIDI_DRIVER midi_alsa =
|
||||
{
|
||||
MIDI_ALSA, /* id */
|
||||
empty_string, /* name */
|
||||
empty_string, /* desc */
|
||||
"ALSA RawMIDI", /* ASCII name */
|
||||
0, /* voices */
|
||||
0, /* basevoice */
|
||||
0xFFFF, /* max_voices */
|
||||
0, /* def_voices */
|
||||
-1, /* xmin */
|
||||
-1, /* xmax */
|
||||
alsa_rawmidi_detect, /* detect */
|
||||
alsa_rawmidi_init, /* init */
|
||||
alsa_rawmidi_exit, /* exit */
|
||||
NULL, /* set_mixer_volume */
|
||||
NULL, /* get_mixer_volume */
|
||||
alsa_rawmidi_output, /* raw_midi */
|
||||
_dummy_load_patches, /* load_patches */
|
||||
_dummy_adjust_patches, /* adjust_patches */
|
||||
_dummy_key_on, /* key_on */
|
||||
_dummy_noop1, /* key_off */
|
||||
_dummy_noop2, /* set_volume */
|
||||
_dummy_noop3, /* set_pitch */
|
||||
_dummy_noop2, /* set_pan */
|
||||
_dummy_noop2 /* set_vibrato */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* alsa_rawmidi_detect:
|
||||
* ALSA RawMIDI detection.
|
||||
*/
|
||||
static int alsa_rawmidi_detect(int input)
|
||||
{
|
||||
#if ALLEGRO_ALSA_VERSION == 9
|
||||
const char *device = NULL;
|
||||
#else /* ALLEGRO_ALSA_VERSION == 5 */
|
||||
int card = -1;
|
||||
int device = -1;
|
||||
#endif
|
||||
int ret = FALSE, err;
|
||||
char tmp1[128], tmp2[128], temp[256];
|
||||
snd_rawmidi_t *handle = NULL;
|
||||
|
||||
if (input) {
|
||||
ret = FALSE;
|
||||
}
|
||||
else {
|
||||
#if ALLEGRO_ALSA_VERSION == 9
|
||||
device = get_config_string(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_rawmidi_device", tmp2),
|
||||
"default");
|
||||
|
||||
err = snd_rawmidi_open(NULL, &handle, device, 0);
|
||||
#else /* ALLEGRO_ALSA_VERSION == 5 */
|
||||
card = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_rawmidi_card", tmp2),
|
||||
snd_defaults_rawmidi_card());
|
||||
|
||||
device = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_rawmidi_device", tmp2),
|
||||
snd_defaults_rawmidi_device());
|
||||
|
||||
err = snd_rawmidi_open(&handle, card, device, SND_RAWMIDI_OPEN_OUTPUT_APPEND);
|
||||
#endif
|
||||
if (err) {
|
||||
snprintf(temp, sizeof(temp), "Could not open card/rawmidi device: %s", snd_strerror(err));
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(temp));
|
||||
ret = FALSE;
|
||||
}
|
||||
else {
|
||||
snd_rawmidi_close(handle);
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_rawmidi_init:
|
||||
* Inits the ALSA RawMIDI interface.
|
||||
*/
|
||||
static int alsa_rawmidi_init(int input, int voices)
|
||||
{
|
||||
int ret = -1, err;
|
||||
char tmp1[128], tmp2[128], temp[256];
|
||||
#if ALLEGRO_ALSA_VERSION == 9
|
||||
snd_rawmidi_info_t *info;
|
||||
const char *device = NULL;
|
||||
#else /* ALLEGRO_ALSA_VERSION == 5 */
|
||||
snd_rawmidi_info_t info;
|
||||
int card = -1;
|
||||
int device = -1;
|
||||
#endif
|
||||
|
||||
if (input) {
|
||||
ret = -1;
|
||||
}
|
||||
else {
|
||||
#if ALLEGRO_ALSA_VERSION == 9
|
||||
device = get_config_string(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_rawmidi_device", tmp2),
|
||||
"default");
|
||||
|
||||
err = snd_rawmidi_open(NULL, &rawmidi_handle, device, 0);
|
||||
#else /* ALLEGRO_ALSA_VERSION == 5 */
|
||||
card = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_rawmidi_card", tmp2),
|
||||
snd_defaults_rawmidi_card());
|
||||
|
||||
device = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("alsa_rawmidi_device", tmp2),
|
||||
snd_defaults_rawmidi_device());
|
||||
|
||||
err = snd_rawmidi_open(&rawmidi_handle, card, device, SND_RAWMIDI_OPEN_OUTPUT_APPEND);
|
||||
#endif
|
||||
if (err) {
|
||||
snprintf(temp, sizeof(temp), "Could not open card/rawmidi device: %s", snd_strerror(err));
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(temp));
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (rawmidi_handle) {
|
||||
#if ALLEGRO_ALSA_VERSION == 9
|
||||
snd_rawmidi_nonblock(rawmidi_handle, 0);
|
||||
snd_rawmidi_info_malloc(&info);
|
||||
snd_rawmidi_info(rawmidi_handle, info);
|
||||
_al_sane_strncpy(alsa_rawmidi_desc, snd_rawmidi_info_get_name(info), sizeof(alsa_rawmidi_desc));
|
||||
#else /* ALLEGRO_ALSA_VERSION == 5 */
|
||||
snd_rawmidi_block_mode(rawmidi_handle, 1);
|
||||
snd_rawmidi_info(rawmidi_handle, &info);
|
||||
_al_sane_strncpy(alsa_rawmidi_desc, info.name, sizeof(alsa_rawmidi_desc));
|
||||
#endif
|
||||
midi_alsa.desc = alsa_rawmidi_desc;
|
||||
alsa_rawmidi_errors = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_rawmidi_exit:
|
||||
* Cleans up.
|
||||
*/
|
||||
static void alsa_rawmidi_exit(int input)
|
||||
{
|
||||
if (rawmidi_handle) {
|
||||
#if ALLEGRO_ALSA_VERSION == 9
|
||||
snd_rawmidi_drain(rawmidi_handle);
|
||||
#else /* ALLEGRO_ALSA_VERSION == 5 */
|
||||
snd_rawmidi_output_drain(rawmidi_handle);
|
||||
#endif
|
||||
snd_rawmidi_close(rawmidi_handle);
|
||||
}
|
||||
|
||||
rawmidi_handle = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* alsa_rawmidi_output:
|
||||
* Outputs MIDI data.
|
||||
*/
|
||||
static void alsa_rawmidi_output(int data)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* If there are too many errors, just give up. Otherwise the calling thread
|
||||
* can end up consuming CPU time for no reason. It probably means the user
|
||||
* hasn't configured ALSA properly.
|
||||
*/
|
||||
if (alsa_rawmidi_errors > ALSA_RAWMIDI_MAX_ERRORS) {
|
||||
return;
|
||||
}
|
||||
|
||||
err = snd_rawmidi_write(rawmidi_handle, &data, sizeof(char));
|
||||
if (err) {
|
||||
alsa_rawmidi_errors++;
|
||||
if (alsa_rawmidi_errors == ALSA_RAWMIDI_MAX_ERRORS) {
|
||||
TRACE("al-alsamidi: too many errors, giving up\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ALLEGRO_MODULE
|
||||
|
||||
/* _module_init:
|
||||
* Called when loaded as a dynamically linked module.
|
||||
*/
|
||||
void _module_init(int system_driver)
|
||||
{
|
||||
_unix_register_midi_driver(MIDI_ALSA, &midi_alsa, TRUE, TRUE);
|
||||
}
|
||||
|
||||
#endif /* ALLEGRO_MODULE */
|
||||
|
||||
#endif /* MIDI_ALSA */
|
||||
|
@ -1,317 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* aRts sound driver (using artsc).
|
||||
*
|
||||
* By Peter Wang.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#include "allegro.h"
|
||||
|
||||
#if (defined ALLEGRO_WITH_ARTSDIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))
|
||||
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintunix.h"
|
||||
|
||||
#include <artsc.h>
|
||||
|
||||
#ifdef ALLEGRO_MODULE
|
||||
int _module_has_registered_via_atexit = 0;
|
||||
#endif
|
||||
|
||||
static int _al_arts_bits, _al_arts_rate, _al_arts_stereo;
|
||||
#define _al_arts_signed (TRUE)
|
||||
|
||||
static arts_stream_t _al_arts_stream = NULL;
|
||||
static int _al_arts_bufsize;
|
||||
static int _al_arts_fragments;
|
||||
static unsigned char *_al_arts_bufdata = NULL;
|
||||
|
||||
static int _al_arts_detect(int input);
|
||||
static int _al_arts_init(int input, int voices);
|
||||
static void _al_arts_exit(int input);
|
||||
static int _al_arts_buffer_size(void);
|
||||
|
||||
static char _al_arts_desc[256] = EMPTY_STRING;
|
||||
|
||||
DIGI_DRIVER digi_arts =
|
||||
{
|
||||
DIGI_ARTS,
|
||||
empty_string,
|
||||
empty_string,
|
||||
"aRts",
|
||||
0,
|
||||
0,
|
||||
MIXER_MAX_SFX,
|
||||
MIXER_DEF_SFX,
|
||||
|
||||
_al_arts_detect,
|
||||
_al_arts_init,
|
||||
_al_arts_exit,
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
_al_arts_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_arts_buffer_size:
|
||||
* Returns the current DMA buffer size, for use by the audiostream code.
|
||||
*/
|
||||
static int _al_arts_buffer_size(void)
|
||||
{
|
||||
return _al_arts_bufsize / (_al_arts_bits / 8) / (_al_arts_stereo ? 2 : 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _al_arts_update:
|
||||
* Update data.
|
||||
*/
|
||||
static void _al_arts_update(int threaded)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _al_arts_fragments; i++) {
|
||||
if (arts_write(_al_arts_stream, _al_arts_bufdata, _al_arts_bufsize)
|
||||
< _al_arts_bufsize)
|
||||
break;
|
||||
_mix_some_samples((uintptr_t) _al_arts_bufdata, 0, _al_arts_signed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define copy_error_text(code, tmp) \
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, \
|
||||
uconvert_ascii(arts_error_text(code), (tmp)));
|
||||
|
||||
|
||||
|
||||
/* _al_arts_detect:
|
||||
* Detect driver presence.
|
||||
*/
|
||||
static int _al_arts_detect(int input)
|
||||
{
|
||||
char tmp[ALLEGRO_ERROR_SIZE];
|
||||
int code;
|
||||
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE,
|
||||
get_config_text("Input is not supported"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
code = arts_init();
|
||||
if (code != 0) {
|
||||
copy_error_text(code, tmp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
arts_free();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _al_arts_init:
|
||||
* Init routine.
|
||||
*/
|
||||
static int _al_arts_init(int input, int voices)
|
||||
{
|
||||
char tmp1[ALLEGRO_ERROR_SIZE];
|
||||
char tmp2[128];
|
||||
int code;
|
||||
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE,
|
||||
get_config_text("Input is not supported"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialise artsc library. */
|
||||
code = arts_init();
|
||||
if (code != 0) {
|
||||
copy_error_text(code, tmp1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef ALLEGRO_MODULE
|
||||
/* A side-effect of arts_init() is that it will register an
|
||||
* atexit handler. See umodules.c for this problem.
|
||||
* ??? this seems to be the case only for recent versions.
|
||||
*/
|
||||
_module_has_registered_via_atexit = 1;
|
||||
#endif
|
||||
|
||||
/* Make a copy of the global sound settings. */
|
||||
_al_arts_bits = (_sound_bits == 8) ? 8 : 16;
|
||||
_al_arts_stereo = (_sound_stereo) ? 1 : 0;
|
||||
_al_arts_rate = (_sound_freq > 0) ? _sound_freq : 44100;
|
||||
|
||||
/* Open a stream for playback. */
|
||||
_al_arts_stream = arts_play_stream(_al_arts_rate, _al_arts_bits,
|
||||
_al_arts_stereo ? 2 : 1,
|
||||
"allegro");
|
||||
if (!_al_arts_stream) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE,
|
||||
get_config_text("Can not open audio stream"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Need non-blocking writes. */
|
||||
code = arts_stream_set(_al_arts_stream, ARTS_P_BLOCKING, 0);
|
||||
if (code != 0) {
|
||||
copy_error_text(code, tmp1);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Try to reduce the latency of our stream. */
|
||||
if (arts_stream_get(_al_arts_stream, ARTS_P_BUFFER_TIME) > 100)
|
||||
arts_stream_set(_al_arts_stream, ARTS_P_BUFFER_TIME, 100);
|
||||
|
||||
/* Read buffer parameters and allocate buffer space. */
|
||||
_al_arts_bufsize = arts_stream_get(_al_arts_stream, ARTS_P_PACKET_SIZE);
|
||||
_al_arts_fragments = arts_stream_get(_al_arts_stream, ARTS_P_PACKET_COUNT);
|
||||
_al_arts_bufdata = _AL_MALLOC_ATOMIC(_al_arts_bufsize);
|
||||
if (!_al_arts_bufdata) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE,
|
||||
get_config_text("Can not allocate audio buffer"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Start up mixer. */
|
||||
digi_arts.voices = voices;
|
||||
|
||||
if (_mixer_init(_al_arts_bufsize / (_al_arts_bits / 8), _al_arts_rate,
|
||||
_al_arts_stereo, ((_al_arts_bits == 16) ? 1 : 0),
|
||||
&digi_arts.voices) != 0) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE,
|
||||
get_config_text("Can not init software mixer"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
_mix_some_samples((uintptr_t) _al_arts_bufdata, 0, _al_arts_signed);
|
||||
|
||||
/* Add audio interrupt. */
|
||||
_unix_bg_man->register_func(_al_arts_update);
|
||||
|
||||
/* Decribe ourself. */
|
||||
uszprintf(_al_arts_desc, sizeof(_al_arts_desc),
|
||||
get_config_text("%s: %d bits, %s, %d bps, %s"),
|
||||
"aRts", _al_arts_bits,
|
||||
uconvert_ascii("signed", tmp1), _al_arts_rate,
|
||||
uconvert_ascii((_al_arts_stereo ? "stereo" : "mono"), tmp2));
|
||||
digi_driver->desc = _al_arts_desc;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
||||
if (_al_arts_bufdata) {
|
||||
_AL_FREE(_al_arts_bufdata);
|
||||
_al_arts_bufdata = NULL;
|
||||
}
|
||||
|
||||
if (_al_arts_stream) {
|
||||
arts_close_stream(_al_arts_stream);
|
||||
_al_arts_stream = NULL;
|
||||
}
|
||||
|
||||
arts_free();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _al_arts_exit:
|
||||
* Shutdown routine.
|
||||
*/
|
||||
static void _al_arts_exit(int input)
|
||||
{
|
||||
if (input)
|
||||
return;
|
||||
|
||||
_unix_bg_man->unregister_func(_al_arts_update);
|
||||
|
||||
_mixer_exit();
|
||||
|
||||
_AL_FREE(_al_arts_bufdata);
|
||||
_al_arts_bufdata = NULL;
|
||||
|
||||
/* Do not call the cleanup routines if we are being
|
||||
* called by the exit mechanism because they may have
|
||||
* already been called by it (see above).
|
||||
*/
|
||||
if (!_allegro_in_exit) {
|
||||
arts_close_stream(_al_arts_stream);
|
||||
_al_arts_stream = NULL;
|
||||
|
||||
arts_free();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ALLEGRO_MODULE
|
||||
|
||||
/* _module_init:
|
||||
* Called when loaded as a dynamically linked module.
|
||||
*/
|
||||
void _module_init(int system_driver)
|
||||
{
|
||||
_unix_register_digi_driver(DIGI_ARTS, &digi_arts, TRUE, TRUE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,336 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* Jack sound driver.
|
||||
*
|
||||
* By Elias Pschernig.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#include "allegro.h"
|
||||
|
||||
#if (defined ALLEGRO_WITH_JACKDIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))
|
||||
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintunix.h"
|
||||
|
||||
#ifndef SCAN_DEPEND
|
||||
#include <jack/jack.h>
|
||||
#endif
|
||||
|
||||
/* This still uses Allegro's mixer, and mixes into an intermediate buffer, which
|
||||
* then is transferred to Jack. Another possibility would be to completely
|
||||
* circumvent Allegro's mixer and send each single voice to jack, letting Jack
|
||||
* take care of the mixing. I didn't care about some things in the Jack docs,
|
||||
* like the possibility of buffer sizes changing, or that no mutex_lock function
|
||||
* should be called (inside mix_some_samples).
|
||||
*/
|
||||
#define JACK_DEFAULT_BUFFER_SIZE -1
|
||||
#define JACK_DEFAULT_CLIENT_NAME "allegro"
|
||||
#define AMP16 ((sample_t) 32768)
|
||||
#define AMP8 ((sample_t) 128)
|
||||
|
||||
#define PREFIX_I "al-jack INFO: "
|
||||
#define PREFIX_W "al-jack WARNING: "
|
||||
#define PREFIX_E "al-jack ERROR: "
|
||||
|
||||
typedef jack_default_audio_sample_t sample_t;
|
||||
|
||||
static int jack_bufsize = JACK_DEFAULT_BUFFER_SIZE;
|
||||
static char const *jack_client_name = JACK_DEFAULT_CLIENT_NAME;
|
||||
static int jack_16bit;
|
||||
static int jack_stereo;
|
||||
static int jack_signed;
|
||||
static jack_nframes_t jack_rate;
|
||||
static char jack_desc[256] = EMPTY_STRING;
|
||||
static jack_client_t *jack_client = NULL;
|
||||
static jack_port_t *output_left, *output_right;
|
||||
static void *jack_buffer;
|
||||
|
||||
static int jack_detect(int input);
|
||||
static int jack_init(int input, int voices);
|
||||
static void jack_exit(int input);
|
||||
static int jack_buffer_size(void);
|
||||
static int jack_set_mixer_volume(int volume);
|
||||
|
||||
DIGI_DRIVER digi_jack =
|
||||
{
|
||||
DIGI_JACK,
|
||||
empty_string,
|
||||
empty_string,
|
||||
"JACK",
|
||||
0,
|
||||
0,
|
||||
MIXER_MAX_SFX,
|
||||
MIXER_DEF_SFX,
|
||||
|
||||
jack_detect,
|
||||
jack_init,
|
||||
jack_exit,
|
||||
jack_set_mixer_volume,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
jack_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
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* jack_buffer_size:
|
||||
* Returns the current buffer size, for use by the audiostream code.
|
||||
*/
|
||||
static int jack_buffer_size(void)
|
||||
{
|
||||
return jack_bufsize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* jack_process:
|
||||
* The JACK processing functions.
|
||||
*/
|
||||
static int jack_process (jack_nframes_t nframes, void *arg)
|
||||
{
|
||||
jack_nframes_t i;
|
||||
/* TODO: Should be uint16_t and uint8_t? Endianess? */
|
||||
unsigned short *buffer16 = jack_buffer;
|
||||
unsigned char *buffer8 = jack_buffer;
|
||||
jack_default_audio_sample_t *out_left;
|
||||
|
||||
_mix_some_samples((uintptr_t) jack_buffer, 0, jack_signed);
|
||||
|
||||
out_left = (jack_default_audio_sample_t *)
|
||||
jack_port_get_buffer (output_left, nframes);
|
||||
|
||||
if (jack_stereo) {
|
||||
jack_default_audio_sample_t *out_right = (jack_default_audio_sample_t *)
|
||||
jack_port_get_buffer (output_right, nframes);
|
||||
|
||||
if (jack_16bit) {
|
||||
for (i = 0; i < nframes; i++) {
|
||||
out_left[i] = ((sample_t) buffer16[i * 2] - AMP16) / AMP16;
|
||||
out_right[i] = ((sample_t) buffer16[i * 2 + 1] - AMP16) / AMP16;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < nframes; i++) {
|
||||
out_left[i] = ((sample_t) buffer8[i * 2] - AMP8) / (sample_t) AMP8;
|
||||
out_right[i] = ((sample_t) buffer8[i * 2 + 1] - AMP8) / (sample_t) AMP8;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (jack_16bit) {
|
||||
for (i = 0; i < nframes; i++) {
|
||||
out_left[i] = ((sample_t) buffer16[i] - AMP16) / AMP16;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < nframes; i++) {
|
||||
out_left[i] = ((sample_t) buffer8[i] - AMP8) / AMP8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* jack_detect:
|
||||
* Detects driver presence.
|
||||
*/
|
||||
static int jack_detect(int input)
|
||||
{
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
|
||||
"Input is not supported"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!jack_client)
|
||||
{
|
||||
jack_client_name = get_config_string("sound", "jack_client_name",
|
||||
jack_client_name);
|
||||
jack_client = jack_client_new(jack_client_name);
|
||||
if (!jack_client)
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* jack_init:
|
||||
* JACK init routine.
|
||||
*/
|
||||
static int jack_init(int input, int voices)
|
||||
{
|
||||
const char **ports;
|
||||
char tmp[128];
|
||||
|
||||
if (!jack_detect(input))
|
||||
return -1;
|
||||
|
||||
jack_bufsize = get_config_int("sound", "jack_buffer_size",
|
||||
jack_bufsize);
|
||||
|
||||
if (jack_bufsize == -1)
|
||||
jack_bufsize = jack_get_buffer_size (jack_client);
|
||||
|
||||
/* Those are already read in from the config file by Allegro. */
|
||||
jack_16bit = (_sound_bits == 16 ? 1 : 0);
|
||||
jack_stereo = (_sound_stereo ? 1 : 0);
|
||||
|
||||
/* Let Allegro mix in its native unsigned format. */
|
||||
jack_signed = 0;
|
||||
|
||||
jack_set_process_callback (jack_client, jack_process, NULL);
|
||||
|
||||
output_left = jack_port_register (jack_client, jack_stereo ? "left" : "mono",
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
|
||||
|
||||
if (jack_stereo)
|
||||
output_right = jack_port_register (jack_client, "right",
|
||||
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
|
||||
|
||||
jack_rate = jack_get_sample_rate (jack_client);
|
||||
|
||||
jack_buffer = _AL_MALLOC_ATOMIC(jack_bufsize * (1 + jack_16bit) * (1 + jack_stereo));
|
||||
if (!jack_buffer) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
|
||||
"Cannot allocate audio buffer"));
|
||||
jack_exit (input);
|
||||
return -1;
|
||||
}
|
||||
|
||||
digi_jack.voices = voices;
|
||||
|
||||
if (_mixer_init(jack_bufsize * (1 + jack_stereo), jack_rate,
|
||||
jack_stereo, jack_16bit, &digi_jack.voices)) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
|
||||
"Cannot init software mixer"));
|
||||
jack_exit (input);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_mix_some_samples((uintptr_t) jack_buffer, 0, jack_signed);
|
||||
|
||||
if (jack_activate (jack_client)) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text(
|
||||
"Cannot activate Jack client"));
|
||||
jack_exit (input);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Try to connect the ports. Failure to connect is not critical, since with
|
||||
* JACK, users may connect/disconnect ports anytime, without Allegro caring.
|
||||
*/
|
||||
if ((ports = jack_get_ports (jack_client, NULL, NULL,
|
||||
JackPortIsPhysical|JackPortIsInput)) == NULL) {
|
||||
TRACE (PREFIX_I "Cannot find any physical playback ports");
|
||||
}
|
||||
|
||||
if (ports) {
|
||||
if (ports[0]) {
|
||||
if (jack_connect (jack_client, jack_port_name (output_left), ports[0]) == 0)
|
||||
TRACE (PREFIX_I "Connected left playback port to %s", ports[0]);
|
||||
}
|
||||
if (jack_stereo && ports[1]) {
|
||||
if (jack_connect (jack_client, jack_port_name (output_right), ports[1]) == 0)
|
||||
TRACE (PREFIX_I "Connected right playback port to %s", ports[1]);
|
||||
}
|
||||
_AL_FREE (ports);
|
||||
}
|
||||
|
||||
uszprintf(jack_desc, sizeof(jack_desc),
|
||||
get_config_text ("Jack, client '%s': %d bits, %s, %d bps, %s"),
|
||||
jack_client_name, jack_16bit ? 16 : 8,
|
||||
uconvert_ascii((jack_signed ? "signed" : "unsigned"), tmp),
|
||||
jack_rate, uconvert_ascii((jack_stereo ? "stereo" : "mono"), tmp));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* jack_exit:
|
||||
* Shuts down the JACK driver.
|
||||
*/
|
||||
static void jack_exit(int input)
|
||||
{
|
||||
jack_client_close (jack_client);
|
||||
jack_client = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* jack_set_mixer_volume:
|
||||
* Set mixer volume (0-255)
|
||||
*/
|
||||
static int jack_set_mixer_volume(int volume)
|
||||
{
|
||||
/* Not implemented */
|
||||
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_JACK, &digi_jack, TRUE, TRUE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,326 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* SGI AL sound driver.
|
||||
*
|
||||
* By Lisa Parratt.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#include "allegro.h"
|
||||
|
||||
#if (defined ALLEGRO_WITH_SGIALDIGI) && ((!defined ALLEGRO_WITH_MODULES) || (defined ALLEGRO_MODULE))
|
||||
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintunix.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <dmedia/audio.h>
|
||||
|
||||
#ifdef ALLEGRO_HAVE_LIBPTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define _AL_SGIAL_PORTSIZE 12288
|
||||
#ifdef ALLEGRO_HAVE_LIBPTHREAD
|
||||
#define _AL_SGIAL_BUFFERSIZE 2048
|
||||
#else
|
||||
#define _AL_SGIAL_BUFFERSIZE 4096
|
||||
#endif
|
||||
|
||||
static ALconfig _al_sgial_config;
|
||||
static ALport _al_sgial_port;
|
||||
static int _al_sgial_bufsize;
|
||||
static unsigned char *_al_sgial_bufdata;
|
||||
static int _al_sgial_signed;
|
||||
|
||||
static int _al_sgial_detect(int input);
|
||||
static int _al_sgial_init(int input, int voices);
|
||||
static void _al_sgial_exit(int input);
|
||||
static int _al_sgial_mixer_volume(int volume);
|
||||
static int _al_sgial_buffer_size(void);
|
||||
|
||||
static char _al_sgial_desc[256] = EMPTY_STRING;
|
||||
|
||||
#ifdef ALLEGRO_HAVE_LIBPTHREAD
|
||||
static pthread_t thread;
|
||||
#endif
|
||||
|
||||
DIGI_DRIVER digi_sgial =
|
||||
{
|
||||
DIGI_SGIAL,
|
||||
empty_string,
|
||||
empty_string,
|
||||
"Silicon Graphics Audio",
|
||||
0,
|
||||
0,
|
||||
MIXER_MAX_SFX,
|
||||
MIXER_DEF_SFX,
|
||||
|
||||
_al_sgial_detect,
|
||||
_al_sgial_init,
|
||||
_al_sgial_exit,
|
||||
_al_sgial_mixer_volume,
|
||||
NULL,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
_al_sgial_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_sgial_buffer_size:
|
||||
* Returns the current DMA buffer size, for use by the audiostream code.
|
||||
*/
|
||||
static int _al_sgial_buffer_size(void)
|
||||
{
|
||||
return _al_sgial_bufsize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef ALLEGRO_HAVE_LIBPTHREAD
|
||||
|
||||
/* _al_sgial_puller_thread_func: [dedicated thread]
|
||||
* We have threads, therefore we can use a thread to pull sound data
|
||||
* as required.
|
||||
*/
|
||||
static void *_al_sgial_puller_thread_func(void *arg)
|
||||
{
|
||||
int fd;
|
||||
fd_set fds;
|
||||
fd = alGetFD(_al_sgial_port);
|
||||
|
||||
while (1) {
|
||||
alSetFillPoint(_al_sgial_port, _AL_SGIAL_PORTSIZE - _AL_SGIAL_BUFFERSIZE);
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
select(FD_SETSIZE, NULL, &fds, NULL, NULL);
|
||||
alWriteFrames(_al_sgial_port, _al_sgial_bufdata, _al_sgial_bufsize);
|
||||
_mix_some_samples((uintptr_t) _al_sgial_bufdata, 0, _al_sgial_signed);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* _al_sgial_update: [SIGALRM callback]
|
||||
* Updates data.
|
||||
*/
|
||||
static void _al_sgial_update(int threaded)
|
||||
{
|
||||
if (alGetFillable(_al_sgial_port) > _al_sgial_bufsize) {
|
||||
alWriteFrames(_al_sgial_port, _al_sgial_bufdata, _al_sgial_bufsize);
|
||||
_mix_some_samples((uintptr_t) _al_sgial_bufdata, 0, _al_sgial_signed);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* _al_sgial_detect:
|
||||
* Detects driver presence.
|
||||
*/
|
||||
static int _al_sgial_detect(int input)
|
||||
{
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* A link error would have occured if the audio library was unavailable */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _al_sgial_init:
|
||||
* SGI AL init routine.
|
||||
* This is different from many systems. Whilst SGI AL supports simultaneous
|
||||
* output, it is assumed that all streams will be at the same sample rate.
|
||||
* This driver is well behaved - as such it does *not* honour requested sample
|
||||
* rates, and always uses the system sample rate.
|
||||
*/
|
||||
static int _al_sgial_init(int input, int voices)
|
||||
{
|
||||
char tmp1[128], tmp2[128];
|
||||
ALpv pv;
|
||||
int _al_sgial_bits;
|
||||
int _al_sgial_stereo;
|
||||
int _al_sgial_rate;
|
||||
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* SGI AL will down/up mix as appropriate. This is a crying waste of
|
||||
* Silicon Graphics audio hardware - in all likelihood it will be
|
||||
* upmixing to 24 bits.
|
||||
*/
|
||||
_al_sgial_bits = (_sound_bits == 8) ? AL_SAMPLE_8: AL_SAMPLE_16;
|
||||
_al_sgial_stereo = (_sound_stereo) ? AL_STEREO : AL_MONO;
|
||||
_al_sgial_signed = 1;
|
||||
|
||||
pv.param = AL_RATE;
|
||||
if (alGetParams(AL_DEFAULT_OUTPUT, &pv, 1) < 0) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not read SGI AL parameters"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
_al_sgial_rate = (int)alFixedToDouble(pv.value.ll);
|
||||
if (_al_sgial_rate < 0) {
|
||||
/* SGI AL couldn't tell us the sample rate: assume 44100 */
|
||||
_al_sgial_rate = 44100;
|
||||
}
|
||||
|
||||
_al_sgial_config = alNewConfig();
|
||||
alSetSampFmt(_al_sgial_config, AL_SAMPFMT_TWOSCOMP);
|
||||
alSetQueueSize(_al_sgial_config, _AL_SGIAL_PORTSIZE);
|
||||
alSetWidth(_al_sgial_config, _al_sgial_bits);
|
||||
alSetChannels(_al_sgial_config, _al_sgial_stereo);
|
||||
|
||||
_al_sgial_port = alOpenPort("Allegro", "w", _al_sgial_config);
|
||||
if (!_al_sgial_port) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not open SGI AL port"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
_al_sgial_bufsize = _AL_SGIAL_BUFFERSIZE;
|
||||
_al_sgial_bufdata = _AL_MALLOC_ATOMIC(_al_sgial_bufsize*((_al_sgial_bits==AL_SAMPLE_16) ? 2 : 1)*((_al_sgial_stereo==AL_STEREO) ? 2 : 1));
|
||||
if (!_al_sgial_bufdata) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer"));
|
||||
alClosePort(_al_sgial_port);
|
||||
alFreeConfig(_al_sgial_config);
|
||||
return -1;
|
||||
}
|
||||
|
||||
digi_sgial.voices = voices;
|
||||
|
||||
if (_mixer_init(_al_sgial_bufsize*((_al_sgial_stereo==AL_STEREO) ? 2 :1 ), _al_sgial_rate,
|
||||
((_al_sgial_stereo == AL_STEREO) ? 1 : 0), ((_al_sgial_bits == AL_SAMPLE_16) ? 1 : 0),
|
||||
&digi_sgial.voices) != 0) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer"));
|
||||
_AL_FREE(_al_sgial_bufdata);
|
||||
alClosePort(_al_sgial_port);
|
||||
alFreeConfig(_al_sgial_config);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_mix_some_samples((uintptr_t) _al_sgial_bufdata, 0, _al_sgial_signed);
|
||||
|
||||
#ifdef ALLEGRO_HAVE_LIBPTHREAD
|
||||
/* Add audio thread. */
|
||||
pthread_create(&thread, NULL, _al_sgial_puller_thread_func, NULL);
|
||||
#else
|
||||
/* Add audio interrupt. */
|
||||
_unix_bg_man->register_func(_al_sgial_update);
|
||||
#endif
|
||||
|
||||
uszprintf(_al_sgial_desc, sizeof(_al_sgial_desc), get_config_text("SGI AL: %d bits, %s, %d bps, %s"),
|
||||
_al_sgial_bits,
|
||||
uconvert_ascii((_al_sgial_signed ? "signed" : "unsigned"), tmp1), _al_sgial_rate,
|
||||
uconvert_ascii((_al_sgial_stereo ? "stereo" : "mono"), tmp2));
|
||||
|
||||
digi_driver->desc = _al_sgial_desc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _al_sgial_exit:
|
||||
* Shutdown SGI AL driver.
|
||||
*/
|
||||
static void _al_sgial_exit(int input)
|
||||
{
|
||||
if (input)
|
||||
return;
|
||||
|
||||
#ifdef ALLEGRO_HAVE_LIBPTHREAD
|
||||
pthread_cancel(thread);
|
||||
#else
|
||||
_unix_bg_man->unregister_func(_al_sgial_update);
|
||||
#endif
|
||||
|
||||
_AL_FREE(_al_sgial_bufdata);
|
||||
_al_sgial_bufdata = NULL;
|
||||
|
||||
_mixer_exit();
|
||||
|
||||
alClosePort(_al_sgial_port);
|
||||
alFreeConfig(_al_sgial_config);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _al_sgial_mixer_volume:
|
||||
* Set mixer volume.
|
||||
*/
|
||||
static int _al_sgial_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_SGIAL, &digi_sgial, TRUE, TRUE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -23,8 +23,6 @@
|
||||
|
||||
|
||||
_DRIVER_INFO *_unix_gfx_driver_list = 0;
|
||||
_DRIVER_INFO *_unix_digi_driver_list = 0;
|
||||
_DRIVER_INFO *_unix_midi_driver_list = 0;
|
||||
|
||||
|
||||
|
||||
@ -36,14 +34,6 @@ void _unix_driver_lists_init(void)
|
||||
_unix_gfx_driver_list = _create_driver_list();
|
||||
if (_unix_gfx_driver_list)
|
||||
_driver_list_append_list(&_unix_gfx_driver_list, _gfx_driver_list);
|
||||
|
||||
_unix_digi_driver_list = _create_driver_list();
|
||||
if (_unix_digi_driver_list)
|
||||
_driver_list_append_list(&_unix_digi_driver_list, _digi_driver_list);
|
||||
|
||||
_unix_midi_driver_list = _create_driver_list();
|
||||
if (_unix_midi_driver_list)
|
||||
_driver_list_append_list(&_unix_midi_driver_list, _midi_driver_list);
|
||||
}
|
||||
|
||||
|
||||
@ -57,16 +47,6 @@ void _unix_driver_lists_shutdown(void)
|
||||
_destroy_driver_list(_unix_gfx_driver_list);
|
||||
_unix_gfx_driver_list = 0;
|
||||
}
|
||||
|
||||
if (_unix_digi_driver_list) {
|
||||
_destroy_driver_list(_unix_digi_driver_list);
|
||||
_unix_digi_driver_list = 0;
|
||||
}
|
||||
|
||||
if (_unix_midi_driver_list) {
|
||||
_destroy_driver_list(_unix_midi_driver_list);
|
||||
_unix_midi_driver_list = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -81,30 +61,3 @@ void _unix_register_gfx_driver(int id, GFX_DRIVER *driver, int autodetect, int p
|
||||
else
|
||||
_driver_list_append_driver(&_unix_gfx_driver_list, id, driver, autodetect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _unix_register_digi_driver:
|
||||
* Used by modules to register digital sound drivers.
|
||||
*/
|
||||
void _unix_register_digi_driver(int id, DIGI_DRIVER *driver, int autodetect, int priority)
|
||||
{
|
||||
if (priority)
|
||||
_driver_list_prepend_driver(&_unix_digi_driver_list, id, driver, autodetect);
|
||||
else
|
||||
_driver_list_append_driver(&_unix_digi_driver_list, id, driver, autodetect);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _unix_register_midi_driver:
|
||||
* Used by modules to register MIDI drivers.
|
||||
*/
|
||||
void _unix_register_midi_driver(int id, MIDI_DRIVER *driver, int autodetect, int priority)
|
||||
{
|
||||
if (priority)
|
||||
_driver_list_prepend_driver(&_unix_midi_driver_list, id, driver, autodetect);
|
||||
else
|
||||
_driver_list_append_driver(&_unix_midi_driver_list, id, driver, autodetect);
|
||||
}
|
||||
|
||||
|
@ -1,290 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \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 <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <esd.h>
|
||||
|
||||
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_set_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_set_mixer_volume,
|
||||
NULL,
|
||||
|
||||
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 = _AL_MALLOC_ATOMIC(_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"));
|
||||
_AL_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);
|
||||
|
||||
_AL_FREE(_al_esd_bufdata);
|
||||
_al_esd_bufdata = 0;
|
||||
|
||||
_mixer_exit();
|
||||
|
||||
close(_al_esd_fd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _al_esd_set_mixer_volume:
|
||||
* Set mixer volume.
|
||||
*/
|
||||
static int _al_esd_set_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
|
||||
|
@ -1,615 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* Open Sound System driver. Supports for /dev/dsp and /dev/audio.
|
||||
*
|
||||
* By Joshua Heyer.
|
||||
*
|
||||
* Modified by Michael Bukin.
|
||||
*
|
||||
* Input code by Peter Wang.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#include "allegro.h"
|
||||
|
||||
#ifdef ALLEGRO_WITH_OSSDIGI
|
||||
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintunix.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#if defined(ALLEGRO_HAVE_SOUNDCARD_H)
|
||||
#include <soundcard.h>
|
||||
#elif defined(ALLEGRO_HAVE_SYS_SOUNDCARD_H)
|
||||
#include <sys/soundcard.h>
|
||||
#elif defined(ALLEGRO_HAVE_MACHINE_SOUNDCARD_H)
|
||||
#include <machine/soundcard.h>
|
||||
#elif defined(ALLEGRO_HAVE_LINUX_SOUNDCARD_H)
|
||||
#include <linux/soundcard.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
|
||||
#ifndef AFMT_S16_NE
|
||||
#ifdef ALLEGRO_BIG_ENDIAN
|
||||
#define AFMT_S16_NE AFMT_S16_BE
|
||||
#else
|
||||
#define AFMT_S16_NE AFMT_S16_LE
|
||||
#endif
|
||||
#endif
|
||||
#ifndef AFMT_U16_NE
|
||||
#ifdef ALLEGRO_BIG_ENDIAN
|
||||
#define AFMT_U16_NE AFMT_U16_BE
|
||||
#else
|
||||
#define AFMT_U16_NE AFMT_U16_LE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#define OSS_DEFAULT_FRAGBITS 9
|
||||
#define OSS_DEFAULT_NUMFRAGS 8
|
||||
|
||||
int _oss_fragsize;
|
||||
int _oss_numfrags;
|
||||
|
||||
char _oss_driver[256] = EMPTY_STRING;
|
||||
static char _oss_mixer_driver[256] = EMPTY_STRING;
|
||||
|
||||
static int oss_fd;
|
||||
static int oss_bufsize;
|
||||
static unsigned char *oss_bufdata;
|
||||
static int oss_signed, oss_format;
|
||||
|
||||
static int oss_save_bits, oss_save_stereo, oss_save_freq;
|
||||
static int oss_rec_bufsize;
|
||||
|
||||
static int oss_detect(int input);
|
||||
static int oss_init(int input, int voices);
|
||||
static void oss_exit(int input);
|
||||
static int oss_set_mixer_volume(int volume);
|
||||
static int oss_get_mixer_volume(void);
|
||||
static int oss_buffer_size(void);
|
||||
static int oss_rec_cap_rate(int bits, int stereo);
|
||||
static int oss_rec_cap_parm(int rate, int bits, int stereo);
|
||||
static int oss_rec_source(int source);
|
||||
static int oss_rec_start(int rate, int bits, int stereo);
|
||||
static void oss_rec_stop(void);
|
||||
static int oss_rec_read(void *buf);
|
||||
|
||||
static char oss_desc[256] = EMPTY_STRING;
|
||||
|
||||
DIGI_DRIVER digi_oss =
|
||||
{
|
||||
DIGI_OSS,
|
||||
empty_string,
|
||||
empty_string,
|
||||
"Open Sound System",
|
||||
0,
|
||||
0,
|
||||
MIXER_MAX_SFX,
|
||||
MIXER_DEF_SFX,
|
||||
|
||||
oss_detect,
|
||||
oss_init,
|
||||
oss_exit,
|
||||
oss_set_mixer_volume,
|
||||
oss_get_mixer_volume,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
oss_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,
|
||||
oss_rec_cap_rate,
|
||||
oss_rec_cap_parm,
|
||||
oss_rec_source,
|
||||
oss_rec_start,
|
||||
oss_rec_stop,
|
||||
oss_rec_read
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* oss_buffer_size:
|
||||
* Returns the current DMA buffer size, for use by the audiostream code.
|
||||
*/
|
||||
static int oss_buffer_size(void)
|
||||
{
|
||||
return oss_bufsize / (_sound_bits / 8) / (_sound_stereo ? 2 : 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_update:
|
||||
* Update data.
|
||||
*/
|
||||
static void oss_update(int threaded)
|
||||
{
|
||||
int i;
|
||||
audio_buf_info bufinfo;
|
||||
|
||||
if (ioctl(oss_fd, SNDCTL_DSP_GETOSPACE, &bufinfo) != -1) {
|
||||
/* Write fragments. */
|
||||
for (i = 0; i < bufinfo.fragments; i++) {
|
||||
write(oss_fd, oss_bufdata, oss_bufsize);
|
||||
_mix_some_samples((uintptr_t) oss_bufdata, 0, oss_signed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* open_oss_device:
|
||||
* Shared helper for the detect and init functions, which opens the
|
||||
* audio device and sets the sample mode parameters.
|
||||
*/
|
||||
static int open_oss_device(int input)
|
||||
{
|
||||
char tmp1[128], tmp2[128], tmp3[128];
|
||||
int fragsize, fragbits, bits, stereo, freq;
|
||||
|
||||
ustrzcpy(_oss_driver, sizeof(_oss_driver), get_config_string(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("oss_driver", tmp2),
|
||||
uconvert_ascii("/dev/dsp", tmp3)));
|
||||
|
||||
ustrzcpy(_oss_mixer_driver, sizeof(_oss_mixer_driver), get_config_string(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("oss_mixer_driver", tmp2),
|
||||
uconvert_ascii("/dev/mixer", tmp3)));
|
||||
|
||||
oss_fd = open(uconvert_toascii(_oss_driver, tmp1), (input ? O_RDONLY : O_WRONLY) | O_NONBLOCK);
|
||||
|
||||
if (oss_fd < 0) {
|
||||
uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s: %s"), _oss_driver, ustrerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
_oss_fragsize = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("oss_fragsize", tmp2),
|
||||
-1);
|
||||
|
||||
_oss_numfrags = get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("oss_numfrags", tmp2),
|
||||
-1);
|
||||
|
||||
if (_oss_fragsize < 0)
|
||||
_oss_fragsize = 1 << OSS_DEFAULT_FRAGBITS;
|
||||
|
||||
if (_oss_numfrags < 0)
|
||||
_oss_numfrags = OSS_DEFAULT_NUMFRAGS;
|
||||
|
||||
/* try to detect whether the DSP can do 16 bit sound or not */
|
||||
if (_sound_bits == -1) {
|
||||
/* ask supported formats */
|
||||
if (ioctl(oss_fd, SNDCTL_DSP_GETFMTS, &oss_format) != -1) {
|
||||
if (oss_format & AFMT_S16_NE) _sound_bits = 16;
|
||||
else if (oss_format & AFMT_U16_NE) _sound_bits = 16;
|
||||
else if (oss_format & AFMT_S8) _sound_bits = 8;
|
||||
else if (oss_format & AFMT_U8) _sound_bits = 8;
|
||||
else {
|
||||
/* ask current format */
|
||||
oss_format = 0;
|
||||
if (ioctl(oss_fd, SNDCTL_DSP_SETFMT, &oss_format) != -1) {
|
||||
switch (oss_format) {
|
||||
case AFMT_S16_NE:
|
||||
case AFMT_U16_NE:
|
||||
_sound_bits = 16;
|
||||
break;
|
||||
case AFMT_S8:
|
||||
case AFMT_U8:
|
||||
_sound_bits = 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bits = (_sound_bits == 8) ? 8 : 16;
|
||||
stereo = (_sound_stereo) ? 1 : 0;
|
||||
freq = (_sound_freq > 0) ? _sound_freq : 45454;
|
||||
|
||||
/* fragment size is specified in samples, not in bytes */
|
||||
fragsize = _oss_fragsize * (bits / 8) * (stereo ? 2 : 1);
|
||||
fragsize += fragsize - 1;
|
||||
|
||||
for (fragbits = 0; (fragbits < 16) && (fragsize > 1); fragbits++)
|
||||
fragsize /= 2;
|
||||
|
||||
fragbits = CLAMP(4, fragbits, 16);
|
||||
_oss_numfrags = CLAMP(2, _oss_numfrags, 0x7FFF);
|
||||
|
||||
fragsize = (_oss_numfrags << 16) | fragbits;
|
||||
|
||||
if (ioctl(oss_fd, SNDCTL_DSP_SETFRAGMENT, &fragsize) == -1) {
|
||||
uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Setting fragment size: %s"), ustrerror(errno));
|
||||
close(oss_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_oss_fragsize = (1 << (fragsize & 0xFFFF)) / (bits / 8) / (stereo ? 2 : 1);
|
||||
_oss_numfrags = fragsize >> 16;
|
||||
|
||||
oss_format = ((bits == 16) ? AFMT_S16_NE : AFMT_U8);
|
||||
|
||||
if ((ioctl(oss_fd, SNDCTL_DSP_SETFMT, &oss_format) == -1) ||
|
||||
(ioctl(oss_fd, SNDCTL_DSP_STEREO, &stereo) == -1) ||
|
||||
(ioctl(oss_fd, SNDCTL_DSP_SPEED, &freq) == -1)) {
|
||||
uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Setting DSP parameters: %s"), ustrerror(errno));
|
||||
close(oss_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
oss_signed = 0;
|
||||
|
||||
switch (oss_format) {
|
||||
|
||||
case AFMT_S8:
|
||||
oss_signed = 1;
|
||||
/* fallthrough */
|
||||
|
||||
case AFMT_U8:
|
||||
bits = 8;
|
||||
break;
|
||||
|
||||
case AFMT_S16_NE:
|
||||
oss_signed = 1;
|
||||
/* fallthrough */
|
||||
|
||||
case AFMT_U16_NE:
|
||||
bits = 16;
|
||||
if (sizeof(short) != 2) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
|
||||
close(oss_fd);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Unsupported sample format"));
|
||||
close(oss_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((stereo != 0) && (stereo != 1)) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Not in stereo or mono mode"));
|
||||
close(oss_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_sound_bits = bits;
|
||||
_sound_stereo = stereo;
|
||||
_sound_freq = freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_detect:
|
||||
* Detect driver presence.
|
||||
*/
|
||||
static int oss_detect(int input)
|
||||
{
|
||||
if (input) {
|
||||
if (digi_driver != digi_input_driver) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("OSS output driver must be installed before input can be read"));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (open_oss_device(0) != 0)
|
||||
return FALSE;
|
||||
|
||||
close(oss_fd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_init:
|
||||
* OSS init routine.
|
||||
*/
|
||||
static int oss_init(int input, int voices)
|
||||
{
|
||||
char tmp1[128], tmp2[128];
|
||||
audio_buf_info bufinfo;
|
||||
|
||||
if (input) {
|
||||
digi_driver->rec_cap_bits = 16;
|
||||
digi_driver->rec_cap_stereo = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (open_oss_device(0) != 0)
|
||||
return -1;
|
||||
|
||||
if (ioctl(oss_fd, SNDCTL_DSP_GETOSPACE, &bufinfo) == -1) {
|
||||
uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Getting buffer size: %s"), ustrerror(errno));
|
||||
close(oss_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
oss_bufsize = bufinfo.fragsize;
|
||||
oss_bufdata = _AL_MALLOC_ATOMIC(oss_bufsize);
|
||||
|
||||
if (oss_bufdata == 0) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not allocate audio buffer"));
|
||||
close(oss_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
digi_oss.voices = voices;
|
||||
|
||||
if (_mixer_init(oss_bufsize / (_sound_bits / 8), _sound_freq,
|
||||
_sound_stereo, ((_sound_bits == 16) ? 1 : 0),
|
||||
&digi_oss.voices) != 0) {
|
||||
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Can not init software mixer"));
|
||||
close(oss_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_mix_some_samples((uintptr_t) oss_bufdata, 0, oss_signed);
|
||||
|
||||
/* Add audio interrupt. */
|
||||
_unix_bg_man->register_func(oss_update);
|
||||
|
||||
uszprintf(oss_desc, sizeof(oss_desc), get_config_text("%s: %d bits, %s, %d bps, %s"),
|
||||
_oss_driver, _sound_bits,
|
||||
uconvert_ascii((oss_signed ? "signed" : "unsigned"), tmp1), _sound_freq,
|
||||
uconvert_ascii((_sound_stereo ? "stereo" : "mono"), tmp2));
|
||||
|
||||
digi_driver->desc = oss_desc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_exit:
|
||||
* Shutdown OSS driver.
|
||||
*/
|
||||
static void oss_exit(int input)
|
||||
{
|
||||
if (input) {
|
||||
return;
|
||||
}
|
||||
|
||||
_unix_bg_man->unregister_func(oss_update);
|
||||
|
||||
_AL_FREE(oss_bufdata);
|
||||
oss_bufdata = 0;
|
||||
|
||||
_mixer_exit();
|
||||
|
||||
close(oss_fd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_set_mixer_volume:
|
||||
* Set mixer volume.
|
||||
*/
|
||||
static int oss_set_mixer_volume(int volume)
|
||||
{
|
||||
int fd, vol, ret;
|
||||
char tmp[128];
|
||||
|
||||
fd = open(uconvert_toascii(_oss_mixer_driver, tmp), O_WRONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
vol = (volume * 100) / 255;
|
||||
vol = (vol << 8) | (vol);
|
||||
ret = ioctl(fd, MIXER_WRITE(SOUND_MIXER_PCM), &vol);
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_get_mixer_volume:
|
||||
* Return mixer volume.
|
||||
*/
|
||||
static int oss_get_mixer_volume(void)
|
||||
{
|
||||
int fd, vol;
|
||||
char tmp[128];
|
||||
|
||||
fd = open(uconvert_toascii(_oss_mixer_driver, tmp), O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (ioctl(fd, MIXER_READ(SOUND_MIXER_PCM), &vol) != 0)
|
||||
return -1;
|
||||
close(fd);
|
||||
|
||||
vol = ((vol & 0xff) + (vol >> 8)) / 2;
|
||||
vol = vol * 255 / 100;
|
||||
return vol;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_rec_cap_rate:
|
||||
* Returns maximum input sampling rate.
|
||||
*/
|
||||
static int oss_rec_cap_rate(int bits, int stereo)
|
||||
{
|
||||
return 44100;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_rec_cap_parm:
|
||||
* Returns whether the specified parameters can be set.
|
||||
*/
|
||||
static int oss_rec_cap_parm(int rate, int bits, int stereo)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_rec_source:
|
||||
* Sets the sampling source for audio recording.
|
||||
*/
|
||||
static int oss_rec_source(int source)
|
||||
{
|
||||
int fd, src, ret;
|
||||
char tmp[128];
|
||||
|
||||
fd = open(uconvert_toascii(_oss_mixer_driver, tmp), O_WRONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
switch (source) {
|
||||
case SOUND_INPUT_MIC:
|
||||
src = SOUND_MASK_MIC;
|
||||
break;
|
||||
|
||||
case SOUND_INPUT_LINE:
|
||||
src = SOUND_MASK_LINE;
|
||||
break;
|
||||
|
||||
case SOUND_INPUT_CD:
|
||||
src = SOUND_MASK_CD;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &src);
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_rec_start:
|
||||
* Re-opens device with read-mode and starts recording (half-duplex).
|
||||
* Returns the DMA buffer size if successful.
|
||||
*/
|
||||
|
||||
static int oss_rec_start(int rate, int bits, int stereo)
|
||||
{
|
||||
audio_buf_info bufinfo;
|
||||
|
||||
/* Save current settings, and close playback device. */
|
||||
oss_save_bits = _sound_bits;
|
||||
oss_save_stereo = _sound_stereo;
|
||||
oss_save_freq = _sound_freq;
|
||||
|
||||
_unix_bg_man->unregister_func(oss_update);
|
||||
|
||||
close(oss_fd);
|
||||
|
||||
/* Reopen device for recording. */
|
||||
_sound_bits = bits;
|
||||
_sound_stereo = stereo;
|
||||
_sound_freq = rate;
|
||||
|
||||
if (open_oss_device(1) != 0)
|
||||
return 0;
|
||||
|
||||
if (ioctl(oss_fd, SNDCTL_DSP_GETISPACE, &bufinfo) == -1) {
|
||||
uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Getting buffer size: %s"), ustrerror(errno));
|
||||
close(oss_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
oss_rec_bufsize = bufinfo.fragsize;
|
||||
return oss_rec_bufsize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_rec_stop:
|
||||
* Stops recording and switches the device back to the original mode.
|
||||
*/
|
||||
static void oss_rec_stop(void)
|
||||
{
|
||||
close(oss_fd);
|
||||
|
||||
/* Reopen for playback with saved settings. */
|
||||
_sound_bits = oss_save_bits;
|
||||
_sound_stereo = oss_save_stereo;
|
||||
_sound_freq = oss_save_freq;
|
||||
|
||||
open_oss_device(0);
|
||||
|
||||
_unix_bg_man->register_func(oss_update);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_rec_read:
|
||||
* Retrieves the just recorded buffer, if there is one.
|
||||
*/
|
||||
static int oss_rec_read(void *buf)
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
if (read(oss_fd, buf, oss_rec_bufsize) != oss_rec_bufsize)
|
||||
return 0;
|
||||
|
||||
/* Convert signedness. */
|
||||
if ((_sound_bits == 16) && (oss_signed)) {
|
||||
p = buf;
|
||||
for (i = 0; i < oss_rec_bufsize; i++)
|
||||
p[i] ^= 0x80;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -1,591 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* Open Sound System sequencer support.
|
||||
*
|
||||
* By Peter Wang.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
#include "allegro.h"
|
||||
|
||||
#ifdef ALLEGRO_WITH_OSSMIDI
|
||||
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintunix.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#if defined(ALLEGRO_HAVE_SOUNDCARD_H)
|
||||
#include <soundcard.h>
|
||||
#elif defined(ALLEGRO_HAVE_SYS_SOUNDCARD_H)
|
||||
#include <sys/soundcard.h>
|
||||
#elif defined(ALLEGRO_HAVE_MACHINE_SOUNDCARD_H)
|
||||
#include <machine/soundcard.h>
|
||||
#elif defined(ALLEGRO_HAVE_LINUX_SOUNDCARD_H)
|
||||
#include <linux/soundcard.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#if defined(ALLEGRO_HAVE_LINUX_AWE_VOICE_H)
|
||||
#include <linux/awe_voice.h>
|
||||
#define UOSSMIDI_HAVE_AWE32
|
||||
#endif
|
||||
|
||||
|
||||
/* our patch data */
|
||||
#include "../misc/fm_instr.h"
|
||||
#include "../misc/fm_emu.h"
|
||||
|
||||
|
||||
|
||||
static int oss_midi_detect(int input);
|
||||
static int oss_midi_init(int input, int voices);
|
||||
static void oss_midi_exit(int input);
|
||||
static int oss_midi_set_mixer_volume(int volume);
|
||||
static int oss_midi_get_mixer_volume(void);
|
||||
static void oss_midi_key_on(int inst, int note, int bend, int vol, int pan);
|
||||
static void oss_midi_key_off(int voice);
|
||||
static void oss_midi_set_volume(int voice, int vol);
|
||||
static void oss_midi_set_pitch(int voice, int note, int bend);
|
||||
|
||||
|
||||
|
||||
#define MAX_VOICES 256
|
||||
|
||||
static int seq_fd = -1;
|
||||
static int seq_device;
|
||||
static int seq_synth_type, seq_synth_subtype;
|
||||
static int seq_patch[MAX_VOICES];
|
||||
static int seq_note[MAX_VOICES];
|
||||
static int seq_drum_start;
|
||||
static char seq_desc[256] = EMPTY_STRING;
|
||||
|
||||
static char seq_driver[256] = EMPTY_STRING;
|
||||
static char mixer_driver[256] = EMPTY_STRING;
|
||||
|
||||
SEQ_DEFINEBUF(2048);
|
||||
|
||||
|
||||
|
||||
MIDI_DRIVER midi_oss =
|
||||
{
|
||||
MIDI_OSS,
|
||||
empty_string,
|
||||
empty_string,
|
||||
"Open Sound System",
|
||||
0, 0, 0xFFFF, 0, -1, -1,
|
||||
oss_midi_detect,
|
||||
oss_midi_init,
|
||||
oss_midi_exit,
|
||||
oss_midi_set_mixer_volume,
|
||||
oss_midi_get_mixer_volume,
|
||||
NULL,
|
||||
_dummy_load_patches,
|
||||
_dummy_adjust_patches,
|
||||
oss_midi_key_on,
|
||||
oss_midi_key_off,
|
||||
oss_midi_set_volume,
|
||||
oss_midi_set_pitch,
|
||||
_dummy_noop2, /* TODO */
|
||||
_dummy_noop2 /* TODO */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* as required by the OSS API */
|
||||
void seqbuf_dump(void)
|
||||
{
|
||||
if (_seqbufptr) {
|
||||
write(seq_fd, _seqbuf, _seqbufptr);
|
||||
_seqbufptr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* attempt to open sequencer device */
|
||||
static int seq_attempt_open(void)
|
||||
{
|
||||
char tmp1[128], tmp2[128], tmp3[128];
|
||||
int fd;
|
||||
|
||||
ustrzcpy(seq_driver, sizeof(seq_driver), get_config_string(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("oss_midi_driver", tmp2),
|
||||
uconvert_ascii("/dev/sequencer", tmp3)));
|
||||
|
||||
fd = open(uconvert_toascii(seq_driver, tmp1), O_WRONLY);
|
||||
if (fd < 0)
|
||||
uszprintf(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("%s: %s"), seq_driver, ustrerror(errno));
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* find the best (supported) synth type for device */
|
||||
static int seq_find_synth(int fd)
|
||||
{
|
||||
struct synth_info info;
|
||||
int num_synths, i;
|
||||
char *s;
|
||||
char tmp1[64], tmp2[256];
|
||||
int score = 0, best_score, best_device;
|
||||
|
||||
if (ioctl(fd, SNDCTL_SEQ_NRSYNTHS, &num_synths) == -1)
|
||||
return 0;
|
||||
|
||||
best_device = -1;
|
||||
best_score = 0;
|
||||
|
||||
/* Detect the best device */
|
||||
for (i = 0; i < num_synths; i++) {
|
||||
info.device = i;
|
||||
if (ioctl(fd, SNDCTL_SYNTH_INFO, &info) == -1)
|
||||
return 0;
|
||||
|
||||
switch (info.synth_type) {
|
||||
|
||||
case SYNTH_TYPE_FM:
|
||||
/* FM synthesis is kind of ok */
|
||||
score = 2;
|
||||
break;
|
||||
|
||||
case SYNTH_TYPE_SAMPLE:
|
||||
/* Wavetable MIDI is cool! */
|
||||
score = 3;
|
||||
break;
|
||||
|
||||
case SYNTH_TYPE_MIDI:
|
||||
/* Only weird people want to use the MIDI out port... */
|
||||
/* ... so we don't accept it yet, this can be fixed when
|
||||
* we've got a config file option to select the MIDI device
|
||||
* so then we'll only select this if people specifically
|
||||
* ask for it */
|
||||
score = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (score > best_score) {
|
||||
best_score = score;
|
||||
best_device = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (best_score == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Cool, we got a decent synth type */
|
||||
seq_device = best_device;
|
||||
|
||||
/* Now get more information */
|
||||
info.device = seq_device;
|
||||
if (ioctl(fd, SNDCTL_SYNTH_INFO, &info) == -1)
|
||||
return 0;
|
||||
|
||||
seq_synth_type = info.synth_type;
|
||||
seq_synth_subtype = info.synth_subtype;
|
||||
|
||||
midi_oss.voices = info.nr_voices;
|
||||
if (midi_oss.voices > MAX_VOICES) midi_oss.voices = MAX_VOICES;
|
||||
|
||||
|
||||
switch (seq_synth_type) {
|
||||
|
||||
case SYNTH_TYPE_FM:
|
||||
switch (seq_synth_subtype) {
|
||||
case FM_TYPE_ADLIB:
|
||||
s = uconvert_ascii("Adlib", tmp1);
|
||||
break;
|
||||
case FM_TYPE_OPL3:
|
||||
s = uconvert_ascii("OPL3", tmp1);
|
||||
break;
|
||||
default:
|
||||
s = uconvert_ascii("FM (unknown)", tmp1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SYNTH_TYPE_SAMPLE:
|
||||
switch (seq_synth_subtype) {
|
||||
#ifdef UOSSMIDI_HAVE_AWE32
|
||||
case SAMPLE_TYPE_AWE32:
|
||||
s = uconvert_ascii("AWE32", tmp1);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
s = uconvert_ascii("sample (unknown)", tmp1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SYNTH_TYPE_MIDI:
|
||||
s = uconvert_ascii("MIDI out", tmp1);
|
||||
break;
|
||||
|
||||
default:
|
||||
s = uconvert_ascii("Unknown synth", tmp1);
|
||||
break;
|
||||
}
|
||||
|
||||
uszprintf(seq_desc, sizeof(seq_desc), uconvert_ascii("Open Sound System (%s)", tmp2), s);
|
||||
midi_driver->desc = seq_desc;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* FM synth: load our instrument patches */
|
||||
static void seq_set_fm_patches(int fd)
|
||||
{
|
||||
struct sbi_instrument ins;
|
||||
int i;
|
||||
|
||||
ins.device = seq_device;
|
||||
ins.key = FM_PATCH;
|
||||
memset(ins.operators, 0, sizeof(ins.operators));
|
||||
|
||||
/* instruments */
|
||||
for (i=0; i<128; i++) {
|
||||
ins.channel = i;
|
||||
memcpy(&ins.operators, &fm_instrument[i], sizeof(FM_INSTRUMENT));
|
||||
write(fd, &ins, sizeof(ins));
|
||||
}
|
||||
|
||||
/* (emulated) drums */
|
||||
for (i=0; i<47; i++) {
|
||||
ins.channel = 128+i;
|
||||
memset(ins.operators, 0, sizeof(ins.operators));
|
||||
memcpy(&ins.operators, &fm_emulated_drum[i], sizeof(FM_INSTRUMENT));
|
||||
write(fd, &ins, sizeof(ins));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* FM synth setup */
|
||||
static void seq_setup_fm (void)
|
||||
{
|
||||
seq_set_fm_patches(seq_fd);
|
||||
seq_drum_start = midi_oss.voices - 5;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef UOSSMIDI_HAVE_AWE32
|
||||
/* AWE32 synth setup */
|
||||
static void seq_setup_awe32 (void)
|
||||
{
|
||||
int bits = 0, drums;
|
||||
|
||||
seq_drum_start = midi_oss.voices;
|
||||
if (seq_drum_start > 32) seq_drum_start = 32;
|
||||
|
||||
/* These non-32 cases probably never happen, since the AWE32 has
|
||||
* 32 voices and anything higher needs a new interface... */
|
||||
if (midi_oss.voices <= 1) {
|
||||
drums = 0;
|
||||
} else if (midi_oss.voices <= 4) {
|
||||
drums = 1;
|
||||
} else if (midi_oss.voices <= 32) {
|
||||
drums = midi_oss.voices / 8;
|
||||
} else {
|
||||
drums = 4;
|
||||
}
|
||||
|
||||
#if 0 // I think I got this wrong
|
||||
/* Set the top 'drums' bits of bitfield and decrement seq_drum_start */
|
||||
while (drums--) bits |= (1 << --seq_drum_start);
|
||||
#else
|
||||
/* The AWE driver seems to like receiving all percussion on MIDI channel
|
||||
* 10 (OSS channel 9) */
|
||||
bits = (1<<9);
|
||||
seq_drum_start -= drums;
|
||||
#endif
|
||||
|
||||
/* Tell the AWE which channels are drum channels. No, I don't know
|
||||
* what 'multi' mode is or how to play drums in the other modes.
|
||||
* This is just what playmidi does (except I'm using AWE_PLAY_MULTI
|
||||
* instead of its value, 1). */
|
||||
AWE_SET_CHANNEL_MODE(seq_device, AWE_PLAY_MULTI);
|
||||
AWE_DRUM_CHANNELS(seq_device, bits);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* oss_midi_detect:
|
||||
* Sequencer detection routine.
|
||||
*/
|
||||
static int oss_midi_detect(int input)
|
||||
{
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
seq_fd = seq_attempt_open();
|
||||
if (seq_fd < 0)
|
||||
return FALSE;
|
||||
|
||||
close(seq_fd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_midi_init:
|
||||
* Init the driver.
|
||||
*/
|
||||
static int oss_midi_init(int input, int voices)
|
||||
{
|
||||
char tmp1[128], tmp2[128], tmp3[128];
|
||||
unsigned int i;
|
||||
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
seq_fd = seq_attempt_open();
|
||||
if (seq_fd < 0)
|
||||
return -1;
|
||||
|
||||
if (!seq_find_synth(seq_fd)) {
|
||||
close(seq_fd);
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("No supported synth type found"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ioctl(seq_fd, SNDCTL_SEQ_RESET);
|
||||
|
||||
/* Driver-specific setup */
|
||||
if (seq_synth_type == SYNTH_TYPE_FM) {
|
||||
|
||||
seq_setup_fm();
|
||||
|
||||
} else if (seq_synth_type == SYNTH_TYPE_SAMPLE) {
|
||||
|
||||
#ifdef UOSSMIDI_HAVE_AWE32
|
||||
if (seq_synth_subtype == SAMPLE_TYPE_AWE32) {
|
||||
|
||||
seq_setup_awe32();
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < (sizeof(seq_patch) / sizeof(int)); i++) {
|
||||
seq_patch[i] = -1;
|
||||
seq_note[i] = -1;
|
||||
}
|
||||
|
||||
/* for the mixer routine */
|
||||
ustrzcpy(mixer_driver, sizeof(mixer_driver), get_config_string(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("oss_mixer_driver", tmp2),
|
||||
uconvert_ascii("/dev/mixer", tmp3)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_midi_set_mixer_volume:
|
||||
* Sets the mixer volume for output.
|
||||
*/
|
||||
static int oss_midi_set_mixer_volume(int volume)
|
||||
{
|
||||
int fd, vol, ret;
|
||||
char tmp[128];
|
||||
|
||||
fd = open(uconvert_toascii(mixer_driver, tmp), O_WRONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
vol = (volume * 100) / 255;
|
||||
vol = (vol << 8) | (vol);
|
||||
ret = ioctl(fd, MIXER_WRITE(SOUND_MIXER_SYNTH), &vol);
|
||||
close(fd);
|
||||
|
||||
return ((ret == -1) ? -1 : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_midi_get_mixer_volume:
|
||||
* Returns mixer volume.
|
||||
*/
|
||||
static int oss_midi_get_mixer_volume(void)
|
||||
{
|
||||
int fd, vol;
|
||||
char tmp[128];
|
||||
|
||||
fd = open(uconvert_toascii(mixer_driver, tmp), O_RDONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
if (ioctl(fd, MIXER_READ(SOUND_MIXER_SYNTH), &vol) != 0)
|
||||
return -1;
|
||||
close(fd);
|
||||
|
||||
vol = ((vol & 0xff) + (vol >> 8)) / 2;
|
||||
vol = vol * 255 / 100;
|
||||
return vol;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* get_hardware_voice:
|
||||
* Get the hardware voice corresponding to this virtual voice. The
|
||||
* hardware may support more than one note per voice, in which case
|
||||
* you don't want to terminate old notes on reusing a voice, but when
|
||||
* Allegro reuses a voice it forgets the old note and won't ever send
|
||||
* a keyoff. So we should use more virtual (Allegro) voices than the
|
||||
* channels the hardware provides, and map them down to actual
|
||||
* hardware channels here.
|
||||
*
|
||||
* We also swap voices 9 and 15 (MIDI 10 and 16). This is necessary
|
||||
* because _midi_allocate_voice can only allocate in continuous ranges
|
||||
* -- so we use voices [0,seq_drum_start) for melody and for the
|
||||
* percussion [seq_drum_start,max_voices), as far as Allegro is
|
||||
* concerned. But hardware likes percussion on MIDI 10, so we need to
|
||||
* remap it.
|
||||
*/
|
||||
static int get_hardware_voice (int voice)
|
||||
{
|
||||
int hwvoice = voice;
|
||||
|
||||
/* FIXME: is this OK/useful for other things than AWE32? */
|
||||
if (seq_synth_type != SYNTH_TYPE_FM && seq_drum_start > 0) {
|
||||
|
||||
/* map drums >= 15, everything else < 15 */
|
||||
hwvoice = hwvoice * 15 / seq_drum_start;
|
||||
|
||||
/* fix up so drums are on MIDI channel 10 */
|
||||
if (hwvoice >= 15)
|
||||
hwvoice = 9;
|
||||
else if (hwvoice == 9)
|
||||
hwvoice = 15;
|
||||
|
||||
}
|
||||
|
||||
return hwvoice;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_midi_key_on:
|
||||
* Triggers the specified voice.
|
||||
*/
|
||||
static void oss_midi_key_on(int inst, int note, int bend, int vol, int pan)
|
||||
{
|
||||
int voice, hwvoice;
|
||||
int is_percussion = 0;
|
||||
|
||||
/* percussion? */
|
||||
if (inst > 127) {
|
||||
voice = _midi_allocate_voice(seq_drum_start, midi_driver->voices-1);
|
||||
/* TODO: Peter's code decrements inst by 35; but the AWE driver
|
||||
* ignores inst completely, using note instead, as God (well, GM)
|
||||
* intended. Does the FM driver ignore note? If so then we're OK. */
|
||||
note = inst-128;
|
||||
inst -= 35;
|
||||
is_percussion = 1;
|
||||
}
|
||||
else
|
||||
voice = _midi_allocate_voice(0, seq_drum_start-1);
|
||||
|
||||
if (voice < 0)
|
||||
return;
|
||||
|
||||
/* Get the hardware voice corresponding to this virtual voice. */
|
||||
hwvoice = get_hardware_voice (voice);
|
||||
|
||||
/* FIXME: should we do this or not for FM? */
|
||||
if (seq_synth_type != SYNTH_TYPE_FM) {
|
||||
/* Stop any previous note on this voice -- but not if it's percussion */
|
||||
if (!is_percussion && seq_note[voice] != -1) {
|
||||
SEQ_STOP_NOTE(seq_device, hwvoice, seq_note[voice], 64);
|
||||
}
|
||||
}
|
||||
seq_note[voice] = note;
|
||||
|
||||
/* make sure the (hardware) voice is set up with the right sound */
|
||||
if (inst != seq_patch[hwvoice]) {
|
||||
SEQ_SET_PATCH(seq_device, hwvoice, inst);
|
||||
seq_patch[hwvoice] = inst;
|
||||
}
|
||||
|
||||
SEQ_CONTROL(seq_device, hwvoice, CTL_PAN, pan);
|
||||
SEQ_BENDER(seq_device, hwvoice, 8192 + bend);
|
||||
SEQ_START_NOTE(seq_device, hwvoice, note, vol);
|
||||
SEQ_DUMPBUF();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_midi_key_off:
|
||||
* Insert witty remark about this line being unhelpful.
|
||||
*/
|
||||
static void oss_midi_key_off(int voice)
|
||||
{
|
||||
/* Get the hardware voice corresponding to this virtual voice. */
|
||||
int hwvoice = get_hardware_voice (voice);
|
||||
|
||||
SEQ_STOP_NOTE(seq_device, hwvoice, seq_note[voice], 64);
|
||||
SEQ_DUMPBUF();
|
||||
|
||||
seq_note[voice] = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_midi_set_volume:
|
||||
* Sets the volume of the specified voice.
|
||||
*/
|
||||
static void oss_midi_set_volume(int voice, int vol)
|
||||
{
|
||||
SEQ_CONTROL(seq_device, voice, CTL_MAIN_VOLUME, vol);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_midi_set_pitch:
|
||||
* Sets the pitch of the specified voice.
|
||||
*/
|
||||
static void oss_midi_set_pitch(int voice, int note, int bend)
|
||||
{
|
||||
SEQ_CONTROL(seq_device, voice, CTRL_PITCH_BENDER, 8192 + bend);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* oss_midi_exit:
|
||||
* Cleanup when we are finished.
|
||||
*/
|
||||
static void oss_midi_exit(int input)
|
||||
{
|
||||
if (input)
|
||||
return;
|
||||
|
||||
if (seq_fd > 0) {
|
||||
close(seq_fd);
|
||||
seq_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,54 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* List of Unix sound drivers.
|
||||
*
|
||||
* By Michael Bukin.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#include "allegro.h"
|
||||
|
||||
|
||||
|
||||
BEGIN_DIGI_DRIVER_LIST
|
||||
#if (defined ALLEGRO_WITH_JACKDIGI) && (!defined ALLEGRO_WITH_MODULES)
|
||||
DIGI_DRIVER_JACK
|
||||
#endif
|
||||
#if (defined ALLEGRO_WITH_SGIALDIGI) && (!defined ALLEGRO_WITH_MODULES)
|
||||
DIGI_DRIVER_SGIAL
|
||||
#endif
|
||||
#if (defined ALLEGRO_WITH_ARTSDIGI) && (!defined ALLEGRO_WITH_MODULES)
|
||||
DIGI_DRIVER_ARTS
|
||||
#endif
|
||||
#if (defined ALLEGRO_WITH_ESDDIGI) && (!defined ALLEGRO_WITH_MODULES)
|
||||
DIGI_DRIVER_ESD
|
||||
#endif
|
||||
#if (defined ALLEGRO_WITH_ALSADIGI) && (!defined ALLEGRO_WITH_MODULES)
|
||||
DIGI_DRIVER_ALSA
|
||||
#endif
|
||||
#if (defined ALLEGRO_WITH_OSSDIGI)
|
||||
DIGI_DRIVER_OSS
|
||||
#endif
|
||||
END_DIGI_DRIVER_LIST
|
||||
|
||||
|
||||
BEGIN_MIDI_DRIVER_LIST
|
||||
MIDI_DRIVER_DIGMID
|
||||
#if (defined ALLEGRO_WITH_ALSAMIDI) && (!defined ALLEGRO_WITH_MODULES)
|
||||
MIDI_DRIVER_ALSA
|
||||
#endif
|
||||
#if (defined ALLEGRO_WITH_OSSMIDI)
|
||||
MIDI_DRIVER_OSS
|
||||
#endif
|
||||
END_MIDI_DRIVER_LIST
|
||||
|
@ -149,8 +149,6 @@ void _win_switch_out(void)
|
||||
key_dinput_unacquire();
|
||||
mouse_dinput_unacquire();
|
||||
|
||||
midi_switch_out();
|
||||
|
||||
if (win_gfx_driver && win_gfx_driver->switch_out)
|
||||
win_gfx_driver->switch_out();
|
||||
|
||||
|
@ -1,610 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* DirectSound input driver.
|
||||
*
|
||||
* By Nick Kochakian.
|
||||
*
|
||||
* API compliance improvements, enhanced format detection
|
||||
* and bugfixes by Javier Gonzalez.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#define DIRECTSOUND_VERSION 0x0500
|
||||
|
||||
#include "allegro.h"
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintwin.h"
|
||||
|
||||
#ifndef SCAN_DEPEND
|
||||
#ifdef ALLEGRO_MINGW32
|
||||
#undef MAKEFOURCC
|
||||
#endif
|
||||
|
||||
#include <mmsystem.h>
|
||||
#include <dsound.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef ALLEGRO_MSVC
|
||||
#include <mmreg.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ALLEGRO_WINDOWS
|
||||
#error something is wrong with the makefile
|
||||
#endif
|
||||
|
||||
#define PREFIX_I "al-dsinput INFO: "
|
||||
#define PREFIX_W "al-dsinput WARNING: "
|
||||
#define PREFIX_E "al-dsinput ERROR: "
|
||||
|
||||
|
||||
/* sound driver globals */
|
||||
static LPDIRECTSOUNDCAPTURE ds_capture = NULL;
|
||||
static LPDIRECTSOUNDCAPTUREBUFFER ds_capture_buf = NULL;
|
||||
static WAVEFORMATEX dsc_buf_wfx;
|
||||
static unsigned long int ds_capture_buffer_size;
|
||||
static unsigned long int last_capture_pos, input_wave_bytes_read;
|
||||
static unsigned char *input_wave_data = NULL;
|
||||
|
||||
|
||||
|
||||
/* ds_err:
|
||||
* Returns a DirectSound error string.
|
||||
*/
|
||||
#ifdef DEBUGMODE
|
||||
static char *ds_err(long err)
|
||||
{
|
||||
static char err_str[64];
|
||||
|
||||
switch (err) {
|
||||
|
||||
case DS_OK:
|
||||
_al_sane_strncpy(err_str, "DS_OK", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_ALLOCATED:
|
||||
_al_sane_strncpy(err_str, "DSERR_ALLOCATED", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_BADFORMAT:
|
||||
_al_sane_strncpy(err_str, "DSERR_BADFORMAT", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_INVALIDPARAM:
|
||||
_al_sane_strncpy(err_str, "DSERR_INVALIDPARAM", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_NOAGGREGATION:
|
||||
_al_sane_strncpy(err_str, "DSERR_NOAGGREGATION", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_OUTOFMEMORY:
|
||||
_al_sane_strncpy(err_str, "DSERR_OUTOFMEMORY", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_UNINITIALIZED:
|
||||
_al_sane_strncpy(err_str, "DSERR_UNINITIALIZED", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_UNSUPPORTED:
|
||||
_al_sane_strncpy(err_str, "DSERR_UNSUPPORTED", sizeof(err_str));
|
||||
break;
|
||||
|
||||
default:
|
||||
_al_sane_strncpy(err_str, "DSERR_UNKNOWN", sizeof(err_str));
|
||||
break;
|
||||
}
|
||||
|
||||
return err_str;
|
||||
}
|
||||
#else
|
||||
#define ds_err(hr) "\0"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* create_test_capture_buffer:
|
||||
* Helper function that tries to create a capture buffer with
|
||||
* the specified format and deletes it immediatly.
|
||||
*/
|
||||
static int create_test_capture_buffer(WAVEFORMATEX *wfx)
|
||||
{
|
||||
LPDIRECTSOUNDCAPTUREBUFFER dsc_trybuf;
|
||||
DSCBUFFERDESC dsc_trybuf_desc;
|
||||
HRESULT hr;
|
||||
|
||||
/* create the capture buffer */
|
||||
ZeroMemory(&dsc_trybuf_desc, sizeof(DSCBUFFERDESC));
|
||||
dsc_trybuf_desc.dwSize = sizeof(DSCBUFFERDESC);
|
||||
dsc_trybuf_desc.dwFlags = 0;
|
||||
dsc_trybuf_desc.dwBufferBytes = 1024;
|
||||
dsc_trybuf_desc.dwReserved = 0;
|
||||
dsc_trybuf_desc.lpwfxFormat = wfx;
|
||||
|
||||
hr = IDirectSoundCapture_CreateCaptureBuffer(ds_capture, &dsc_trybuf_desc, &dsc_trybuf, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return -1;
|
||||
|
||||
IDirectSoundCaptureBuffer_Release(dsc_trybuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* get_capture_format_support:
|
||||
* Helper function to see if the specified input device
|
||||
* can support a combination of capture settings.
|
||||
*/
|
||||
static int get_capture_format_support(int bits, int stereo, int rate,
|
||||
int autodetect, WAVEFORMATEX *wfx)
|
||||
{
|
||||
int i;
|
||||
DSCCAPS dsCaps;
|
||||
HRESULT hr;
|
||||
WAVEFORMATEX *test_wfx;
|
||||
|
||||
struct {
|
||||
unsigned long int type;
|
||||
unsigned long int freq;
|
||||
unsigned char bits;
|
||||
unsigned char channels;
|
||||
BOOL stereo;
|
||||
} ds_formats[] = {
|
||||
{ WAVE_FORMAT_4S16, 44100, 16, 2, TRUE },
|
||||
{ WAVE_FORMAT_2S16, 22050, 16, 2, TRUE },
|
||||
{ WAVE_FORMAT_1S16, 11025, 16, 2, TRUE },
|
||||
|
||||
{ WAVE_FORMAT_4M16, 44100, 16, 1, FALSE },
|
||||
{ WAVE_FORMAT_2M16, 22050, 16, 1, FALSE },
|
||||
{ WAVE_FORMAT_1M16, 11025, 16, 1, FALSE },
|
||||
|
||||
{ WAVE_FORMAT_4S08, 44100, 8, 2, TRUE },
|
||||
{ WAVE_FORMAT_2S08, 22050, 8, 2, TRUE },
|
||||
{ WAVE_FORMAT_1S08, 11025, 8, 2, TRUE },
|
||||
|
||||
{ WAVE_FORMAT_4M08, 44100, 8, 1, FALSE },
|
||||
{ WAVE_FORMAT_2M08, 22050, 8, 1, FALSE },
|
||||
{ WAVE_FORMAT_1M08, 11025, 8, 1, FALSE },
|
||||
|
||||
{ WAVE_INVALIDFORMAT, 0, 0, 0, FALSE }
|
||||
};
|
||||
|
||||
if (!ds_capture)
|
||||
return -1;
|
||||
|
||||
/* if we have already a capture buffer working
|
||||
* we return its format as the only valid one
|
||||
*/
|
||||
if (ds_capture_buf) {
|
||||
if (!autodetect) {
|
||||
/* we must check that everything that cares is
|
||||
* the same as in the capture buffer settings
|
||||
*/
|
||||
if (((bits > 0) && (dsc_buf_wfx.wBitsPerSample != bits)) ||
|
||||
( stereo && (dsc_buf_wfx.nChannels != 2)) ||
|
||||
(!stereo && (dsc_buf_wfx.nChannels != 1)) ||
|
||||
((rate > 0) && (dsc_buf_wfx.nSamplesPerSec != (unsigned int) rate)))
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* return the actual capture buffer settings */
|
||||
if (wfx)
|
||||
memcpy(wfx, &dsc_buf_wfx, sizeof(WAVEFORMATEX));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we use a two-level checking process:
|
||||
* - the normal check of exposed capabilities,
|
||||
* - the actual creation of the capture buffer,
|
||||
* because of the single frequency limitation on some
|
||||
* sound cards (e.g SB16 ISA) in full duplex mode.
|
||||
*/
|
||||
dsCaps.dwSize = sizeof(DSCCAPS);
|
||||
hr = IDirectSoundCapture_GetCaps(ds_capture, &dsCaps);
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "Can't get input device caps (%s).\n", ds_err(hr));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wfx)
|
||||
test_wfx = wfx;
|
||||
else
|
||||
test_wfx = _AL_MALLOC(sizeof(WAVEFORMATEX));
|
||||
|
||||
for (i=0; ds_formats[i].type != WAVE_INVALIDFORMAT; i++)
|
||||
/* if the current format is supported */
|
||||
if (dsCaps.dwFormats & ds_formats[i].type) {
|
||||
if (!autodetect) {
|
||||
/* we must check that everything that cares is
|
||||
* the same as in the capture buffer settings
|
||||
*/
|
||||
if (((bits > 0) && (ds_formats[i].bits != bits)) ||
|
||||
(stereo && !ds_formats[i].stereo) ||
|
||||
(!stereo && ds_formats[i].stereo) ||
|
||||
((rate > 0) && (ds_formats[i].freq != (unsigned int) rate)))
|
||||
continue; /* go to next format */
|
||||
}
|
||||
|
||||
test_wfx->wFormatTag = WAVE_FORMAT_PCM;
|
||||
test_wfx->nChannels = ds_formats[i].channels;
|
||||
test_wfx->nSamplesPerSec = ds_formats[i].freq;
|
||||
test_wfx->wBitsPerSample = ds_formats[i].bits;
|
||||
test_wfx->nBlockAlign = test_wfx->nChannels * (test_wfx->wBitsPerSample / 8);
|
||||
test_wfx->nAvgBytesPerSec = test_wfx->nSamplesPerSec * test_wfx->nBlockAlign;
|
||||
test_wfx->cbSize = 0;
|
||||
|
||||
if (create_test_capture_buffer(test_wfx) == 0) {
|
||||
if (!wfx)
|
||||
_AL_FREE(test_wfx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!wfx)
|
||||
_AL_FREE(test_wfx);
|
||||
|
||||
_TRACE(PREFIX_W "No valid recording formats found.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_directsound_capture_init:
|
||||
*/
|
||||
int digi_directsound_capture_init(LPGUID guid)
|
||||
{
|
||||
DSCCAPS dsCaps;
|
||||
WAVEFORMATEX wfx;
|
||||
HRESULT hr;
|
||||
LPVOID temp;
|
||||
|
||||
/* the DirectSoundCapture interface is not part of DirectX 3 */
|
||||
if (_dx_ver < 0x0500)
|
||||
return -1;
|
||||
|
||||
/* create the device:
|
||||
* we use CoCreateInstance() instead of DirectSoundCaptureCreate() to avoid
|
||||
* the dll loader blocking the start of Allegro under DirectX 3.
|
||||
*/
|
||||
|
||||
hr = CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_IDirectSoundCapture, &temp);
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "Can't create DirectSoundCapture interface (%s).\n", ds_err(hr));
|
||||
goto Error;
|
||||
}
|
||||
|
||||
ds_capture = temp;
|
||||
|
||||
/* initialize the device */
|
||||
hr = IDirectSoundCapture_Initialize(ds_capture, guid);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
hr = IDirectSoundCapture_Initialize(ds_capture, NULL);
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "Can't initialize DirectSoundCapture interface (%s).\n", ds_err(hr));
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the device caps */
|
||||
dsCaps.dwSize = sizeof(DSCCAPS);
|
||||
hr = IDirectSoundCapture_GetCaps(ds_capture, &dsCaps);
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "Can't get input device caps (%s).\n", ds_err(hr));
|
||||
goto Error;
|
||||
}
|
||||
|
||||
/* cool little 'autodetection' process :) */
|
||||
if (get_capture_format_support(0, FALSE, 0, TRUE, &wfx) != 0) {
|
||||
_TRACE(PREFIX_E "The DirectSound hardware doesn't support any capture types.\n");
|
||||
goto Error;
|
||||
}
|
||||
|
||||
/* set capabilities */
|
||||
digi_input_driver->rec_cap_bits = wfx.wBitsPerSample;
|
||||
digi_input_driver->rec_cap_stereo = (wfx.nChannels == 2) ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
|
||||
Error:
|
||||
/* shutdown DirectSoundCapture */
|
||||
digi_directsound_capture_exit();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_directsound_capture_exit:
|
||||
*/
|
||||
void digi_directsound_capture_exit(void)
|
||||
{
|
||||
/* destroy capture buffer */
|
||||
digi_directsound_rec_stop();
|
||||
|
||||
/* shutdown DirectSoundCapture */
|
||||
if (ds_capture) {
|
||||
IDirectSoundCapture_Release(ds_capture);
|
||||
ds_capture = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_directsound_capture_detect:
|
||||
*/
|
||||
int digi_directsound_capture_detect(LPGUID guid)
|
||||
{
|
||||
HRESULT hr;
|
||||
LPVOID temp;
|
||||
|
||||
/* the DirectSoundCapture interface is not part of DirectX 3 */
|
||||
if (_dx_ver < 0x500)
|
||||
return 0;
|
||||
|
||||
if (!ds_capture) {
|
||||
/* create the device:
|
||||
* we use CoCreateInstance() instead of DirectSoundCaptureCreate() to avoid
|
||||
* the dll loader blocking the start of Allegro under DirectX 3.
|
||||
*/
|
||||
hr = CoCreateInstance(&CLSID_DirectSoundCapture, NULL, CLSCTX_INPROC_SERVER,
|
||||
&IID_IDirectSoundCapture, &temp);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "DirectSoundCapture interface creation failed during detect (%s).\n", ds_err(hr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ds_capture = temp;
|
||||
|
||||
/* initialize the device */
|
||||
hr = IDirectSoundCapture_Initialize(ds_capture, guid);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
hr = IDirectSoundCapture_Initialize(ds_capture, NULL);
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "DirectSoundCapture interface initialization failed during detect (%s).\n", ds_err(hr));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
_TRACE(PREFIX_I "DirectSoundCapture interface successfully created.\n");
|
||||
|
||||
/* release DirectSoundCapture interface */
|
||||
IDirectSoundCapture_Release(ds_capture);
|
||||
ds_capture = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_directsound_rec_cap_rate:
|
||||
* Gets the maximum input frequency for the specified parameters.
|
||||
*/
|
||||
int digi_directsound_rec_cap_rate(int bits, int stereo)
|
||||
{
|
||||
WAVEFORMATEX wfx;
|
||||
|
||||
if (get_capture_format_support(bits, stereo, 0, FALSE, &wfx) != 0)
|
||||
return 0;
|
||||
|
||||
return wfx.nSamplesPerSec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_directsound_rec_cap_param:
|
||||
* Determines if the combination of provided parameters can be
|
||||
* used for recording.
|
||||
*/
|
||||
int digi_directsound_rec_cap_param(int rate, int bits, int stereo)
|
||||
{
|
||||
if (get_capture_format_support(bits, stereo, rate, FALSE, NULL) == 0)
|
||||
return 2;
|
||||
|
||||
if (get_capture_format_support(bits, stereo, 44100, FALSE, NULL) == 0)
|
||||
return -44100;
|
||||
|
||||
if (get_capture_format_support(bits, stereo, 22050, FALSE, NULL) == 0)
|
||||
return -22050;
|
||||
|
||||
if (get_capture_format_support(bits, stereo, 11025, FALSE, NULL) == 0)
|
||||
return -11025;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_directsound_rec_source:
|
||||
* Sets the source for the audio recording.
|
||||
*/
|
||||
int digi_directsound_rec_source(int source)
|
||||
{
|
||||
/* since DirectSoundCapture doesn't allow us to
|
||||
* select a input source manually, we return -1
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_directsound_rec_start:
|
||||
* Start recording with the specified parameters.
|
||||
*/
|
||||
int digi_directsound_rec_start(int rate, int bits, int stereo)
|
||||
{
|
||||
DSCBUFFERDESC dscBufDesc;
|
||||
HRESULT hr;
|
||||
|
||||
if (!ds_capture || ds_capture_buf)
|
||||
return 0;
|
||||
|
||||
/* check if we support the desired format */
|
||||
if ((bits <= 0) || (rate <= 0))
|
||||
return 0;
|
||||
|
||||
if (get_capture_format_support(bits, stereo, rate, FALSE, &dsc_buf_wfx) != 0)
|
||||
return 0;
|
||||
|
||||
digi_driver->rec_cap_bits = dsc_buf_wfx.wBitsPerSample;
|
||||
digi_driver->rec_cap_stereo = (dsc_buf_wfx.nChannels == 2) ? 1 : 0;
|
||||
|
||||
/* create the capture buffer */
|
||||
ZeroMemory(&dscBufDesc, sizeof(DSCBUFFERDESC));
|
||||
dscBufDesc.dwSize = sizeof(DSCBUFFERDESC);
|
||||
dscBufDesc.dwFlags = 0;
|
||||
dscBufDesc.dwBufferBytes = dsc_buf_wfx.nAvgBytesPerSec;
|
||||
dscBufDesc.dwReserved = 0;
|
||||
dscBufDesc.lpwfxFormat = &dsc_buf_wfx;
|
||||
ds_capture_buffer_size = dscBufDesc.dwBufferBytes;
|
||||
|
||||
hr = IDirectSoundCapture_CreateCaptureBuffer(ds_capture, &dscBufDesc, &ds_capture_buf, NULL);
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "Can't create the DirectSound capture buffer (%s).\n", ds_err(hr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
hr = IDirectSoundCaptureBuffer_Start(ds_capture_buf, DSCBSTART_LOOPING);
|
||||
if (FAILED(hr)) {
|
||||
IDirectSoundCaptureBuffer_Release(ds_capture_buf);
|
||||
ds_capture_buf = NULL;
|
||||
|
||||
_TRACE(PREFIX_E "Can't start the DirectSound capture buffer (%s).\n", ds_err(hr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
last_capture_pos = 0;
|
||||
input_wave_data = _AL_MALLOC(ds_capture_buffer_size);
|
||||
input_wave_bytes_read = 0;
|
||||
|
||||
return ds_capture_buffer_size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_directsound_rec_stop:
|
||||
* Stops recording.
|
||||
*/
|
||||
void digi_directsound_rec_stop(void)
|
||||
{
|
||||
if (ds_capture_buf) {
|
||||
IDirectSoundCaptureBuffer_Stop(ds_capture_buf);
|
||||
IDirectSoundCaptureBuffer_Release(ds_capture_buf);
|
||||
ds_capture_buf = NULL;
|
||||
}
|
||||
|
||||
if (input_wave_data) {
|
||||
_AL_FREE(input_wave_data);
|
||||
input_wave_data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_directsound_rec_read:
|
||||
* Reads the input buffer.
|
||||
*/
|
||||
int digi_directsound_rec_read(void *buf)
|
||||
{
|
||||
unsigned char *input_ptr1, *input_ptr2, *linear_input_ptr;
|
||||
unsigned long int input_bytes1, input_bytes2, bytes_to_lock;
|
||||
unsigned long int capture_pos;
|
||||
HRESULT hr;
|
||||
BOOL buffer_filled = FALSE;
|
||||
LPVOID temp1, temp2;
|
||||
|
||||
if (!ds_capture || !ds_capture_buf || !input_wave_data)
|
||||
return 0;
|
||||
|
||||
IDirectSoundCaptureBuffer_GetCurrentPosition(ds_capture_buf, &capture_pos, NULL);
|
||||
|
||||
/* check if we are not still in the same capture position */
|
||||
if (last_capture_pos == capture_pos)
|
||||
return 0;
|
||||
|
||||
/* check how many bytes we need to lock since last check */
|
||||
if (capture_pos > last_capture_pos) {
|
||||
bytes_to_lock = capture_pos - last_capture_pos;
|
||||
}
|
||||
else {
|
||||
bytes_to_lock = ds_capture_buffer_size - last_capture_pos;
|
||||
bytes_to_lock += capture_pos;
|
||||
}
|
||||
|
||||
hr = IDirectSoundCaptureBuffer_Lock(ds_capture_buf, last_capture_pos,
|
||||
bytes_to_lock, &temp1,
|
||||
&input_bytes1, &temp2,
|
||||
&input_bytes2, 0);
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
|
||||
input_ptr1 = temp1;
|
||||
input_ptr2 = temp2;
|
||||
|
||||
/* let's get the data aligned linearly */
|
||||
linear_input_ptr = _AL_MALLOC(bytes_to_lock);
|
||||
memcpy(linear_input_ptr, input_ptr1, input_bytes1);
|
||||
|
||||
if (input_ptr2)
|
||||
memcpy(linear_input_ptr + input_bytes1, input_ptr2, input_bytes2);
|
||||
|
||||
IDirectSoundCaptureBuffer_Unlock(ds_capture_buf, input_ptr1,
|
||||
input_bytes1, input_ptr2, input_bytes2);
|
||||
|
||||
if ((input_wave_bytes_read + bytes_to_lock) >= ds_capture_buffer_size) {
|
||||
/* we fill the buffer */
|
||||
long int bytes_left_to_fill = ds_capture_buffer_size - input_wave_bytes_read;
|
||||
long int bytes_to_internal = bytes_to_lock - bytes_left_to_fill;
|
||||
|
||||
/* copy old buffer to user buffer */
|
||||
memcpy((char*)buf, input_wave_data, input_wave_bytes_read);
|
||||
|
||||
/* and the rest of bytes we would need to fill in the buffer */
|
||||
memcpy((char*)buf + input_wave_bytes_read, linear_input_ptr, bytes_left_to_fill);
|
||||
|
||||
/* and the rest of the data to the internal buffer */
|
||||
input_wave_bytes_read = bytes_to_internal;
|
||||
memcpy(input_wave_data, linear_input_ptr + bytes_left_to_fill, bytes_to_internal);
|
||||
|
||||
buffer_filled = TRUE;
|
||||
|
||||
/* if we are using 16-bit data, we need to convert it to unsigned format */
|
||||
if (digi_driver->rec_cap_bits == 16) {
|
||||
unsigned int i;
|
||||
unsigned short *buf16 = (unsigned short *)buf;
|
||||
|
||||
for (i = 0; i < ds_capture_buffer_size/2; i++)
|
||||
buf16[i] ^= 0x8000;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* we won't fill the buffer */
|
||||
memcpy(input_wave_data + input_wave_bytes_read, linear_input_ptr, bytes_to_lock);
|
||||
input_wave_bytes_read += bytes_to_lock;
|
||||
}
|
||||
|
||||
_AL_FREE(linear_input_ptr);
|
||||
|
||||
last_capture_pos = capture_pos;
|
||||
|
||||
if (buffer_filled)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
@ -1,752 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* Allegro mixer to DirectSound driver.
|
||||
*
|
||||
* By Robin Burrows.
|
||||
*
|
||||
* Based on original src/win/wdsound.c by Stefan Schimanski
|
||||
* and src/unix/oss.c by Joshua Heyer.
|
||||
*
|
||||
* Bugfixes by Javier Gonzalez.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#define DIRECTSOUND_VERSION 0x0300
|
||||
|
||||
#include "allegro.h"
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintwin.h"
|
||||
|
||||
#ifndef SCAN_DEPEND
|
||||
#ifdef ALLEGRO_MINGW32
|
||||
#undef MAKEFOURCC
|
||||
#endif
|
||||
|
||||
#include <mmsystem.h>
|
||||
#include <dsound.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef ALLEGRO_MSVC
|
||||
#include <mmreg.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ALLEGRO_WINDOWS
|
||||
#error something is wrong with the makefile
|
||||
#endif
|
||||
|
||||
#define PREFIX_I "al-dsndmix INFO: "
|
||||
#define PREFIX_W "al-dsndmix WARNING: "
|
||||
#define PREFIX_E "al-dsndmix ERROR: "
|
||||
|
||||
|
||||
static int digi_dsoundmix_detect(int input);
|
||||
static int digi_dsoundmix_init(int input, int voices);
|
||||
static void digi_dsoundmix_exit(int input);
|
||||
static int digi_dsoundmix_set_mixer_volume(int volume);
|
||||
static int digi_dsoundmix_get_mixer_volume(void);
|
||||
static int digi_dsoundmix_buffer_size(void);
|
||||
|
||||
|
||||
/* template driver: will be cloned for each device */
|
||||
static DIGI_DRIVER digi_dsoundmix =
|
||||
{
|
||||
0,
|
||||
empty_string,
|
||||
empty_string,
|
||||
empty_string,
|
||||
0, // available voices
|
||||
0, // voice number offset
|
||||
MIXER_MAX_SFX, // maximum voices we can support
|
||||
MIXER_DEF_SFX, // default number of voices to use
|
||||
|
||||
/* setup routines */
|
||||
digi_dsoundmix_detect,
|
||||
digi_dsoundmix_init,
|
||||
digi_dsoundmix_exit,
|
||||
digi_dsoundmix_set_mixer_volume,
|
||||
digi_dsoundmix_get_mixer_volume,
|
||||
|
||||
/* audiostream locking functions */
|
||||
NULL, // AL_METHOD(void *, lock_voice, (int voice, int start, int end));
|
||||
NULL, // AL_METHOD(void, unlock_voice, (int voice));
|
||||
digi_dsoundmix_buffer_size,
|
||||
|
||||
/* voice control functions */
|
||||
_mixer_init_voice,
|
||||
_mixer_release_voice,
|
||||
_mixer_start_voice,
|
||||
_mixer_stop_voice,
|
||||
_mixer_loop_voice,
|
||||
|
||||
/* position control functions */
|
||||
_mixer_get_position,
|
||||
_mixer_set_position,
|
||||
|
||||
/* volume control functions */
|
||||
_mixer_get_volume,
|
||||
_mixer_set_volume,
|
||||
_mixer_ramp_volume,
|
||||
_mixer_stop_volume_ramp,
|
||||
|
||||
/* pitch control functions */
|
||||
_mixer_get_frequency,
|
||||
_mixer_set_frequency,
|
||||
_mixer_sweep_frequency,
|
||||
_mixer_stop_frequency_sweep,
|
||||
|
||||
/* pan control functions */
|
||||
_mixer_get_pan,
|
||||
_mixer_set_pan,
|
||||
_mixer_sweep_pan,
|
||||
_mixer_stop_pan_sweep,
|
||||
|
||||
/* effect control functions */
|
||||
_mixer_set_echo,
|
||||
_mixer_set_tremolo,
|
||||
_mixer_set_vibrato,
|
||||
|
||||
/* input functions */
|
||||
0, // int rec_cap_bits;
|
||||
0, // int rec_cap_stereo;
|
||||
digi_directsound_rec_cap_rate,
|
||||
digi_directsound_rec_cap_param,
|
||||
digi_directsound_rec_source,
|
||||
digi_directsound_rec_start,
|
||||
digi_directsound_rec_stop,
|
||||
digi_directsound_rec_read
|
||||
};
|
||||
|
||||
|
||||
#define MAX_DRIVERS 16
|
||||
static char *driver_names[MAX_DRIVERS];
|
||||
static LPGUID driver_guids[MAX_DRIVERS];
|
||||
|
||||
|
||||
#define USE_NEW_CODE 0
|
||||
|
||||
/* sound driver globals */
|
||||
static LPDIRECTSOUND directsound = NULL;
|
||||
static LPDIRECTSOUNDBUFFER prim_buf = NULL;
|
||||
static LPDIRECTSOUNDBUFFER alleg_buf = NULL;
|
||||
static long int initial_volume;
|
||||
static int _freq, _bits, _stereo;
|
||||
static int alleg_to_dsound_volume[256];
|
||||
static unsigned int digidsbufsize;
|
||||
static unsigned char *digidsbufdata;
|
||||
#if !USE_NEW_CODE
|
||||
static unsigned int bufdivs = 16, digidsbufpos;
|
||||
#else
|
||||
static int digidsbufdirty;
|
||||
#endif
|
||||
static int alleg_buf_paused = FALSE;
|
||||
static int alleg_buf_vol;
|
||||
|
||||
|
||||
|
||||
/* ds_err:
|
||||
* Returns a DirectSound error string.
|
||||
*/
|
||||
#ifdef DEBUGMODE
|
||||
static char *ds_err(long err)
|
||||
{
|
||||
static char err_str[64];
|
||||
|
||||
switch (err) {
|
||||
|
||||
case DS_OK:
|
||||
_al_sane_strncpy(err_str, "DS_OK", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_ALLOCATED:
|
||||
_al_sane_strncpy(err_str, "DSERR_ALLOCATED", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_BADFORMAT:
|
||||
_al_sane_strncpy(err_str, "DSERR_BADFORMAT", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_INVALIDPARAM:
|
||||
_al_sane_strncpy(err_str, "DSERR_INVALIDPARAM", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_NOAGGREGATION:
|
||||
_al_sane_strncpy(err_str, "DSERR_NOAGGREGATION", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_OUTOFMEMORY:
|
||||
_al_sane_strncpy(err_str, "DSERR_OUTOFMEMORY", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_UNINITIALIZED:
|
||||
_al_sane_strncpy(err_str, "DSERR_UNINITIALIZED", sizeof(err_str));
|
||||
break;
|
||||
|
||||
case DSERR_UNSUPPORTED:
|
||||
_al_sane_strncpy(err_str, "DSERR_UNSUPPORTED", sizeof(err_str));
|
||||
break;
|
||||
|
||||
default:
|
||||
_al_sane_strncpy(err_str, "DSERR_UNKNOWN", sizeof(err_str));
|
||||
break;
|
||||
}
|
||||
|
||||
return err_str;
|
||||
}
|
||||
#else
|
||||
#define ds_err(hr) "\0"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* _get_dsalmix_driver:
|
||||
* System driver hook for listing the available sound drivers. This
|
||||
* generates the device list at runtime, to match whatever DirectSound
|
||||
* devices are available.
|
||||
*/
|
||||
DIGI_DRIVER *_get_dsalmix_driver(char *name, LPGUID guid, int num)
|
||||
{
|
||||
DIGI_DRIVER *driver;
|
||||
|
||||
driver = _AL_MALLOC(sizeof(DIGI_DRIVER));
|
||||
if (!driver)
|
||||
return NULL;
|
||||
|
||||
memcpy(driver, &digi_dsoundmix, sizeof(DIGI_DRIVER));
|
||||
|
||||
driver->id = DIGI_DIRECTAMX(num);
|
||||
|
||||
driver_names[num] = _AL_MALLOC_ATOMIC(strlen(name)+10);
|
||||
if (driver_names[num]) {
|
||||
_al_sane_strncpy(driver_names[num], "Allegmix ", strlen(name)+10);
|
||||
_al_sane_strncpy(driver_names[num]+9, name, strlen(name)+1);
|
||||
driver->ascii_name = driver_names[num];
|
||||
}
|
||||
|
||||
driver_guids[num] = guid;
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _free_win_dsalmix_name_list
|
||||
* Helper function for freeing dynamically generated driver names.
|
||||
*/
|
||||
void _free_win_dsalmix_name_list(void)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < MAX_DRIVERS; i++) {
|
||||
if (driver_names[i]) _AL_FREE(driver_names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* create_dsound_buffer:
|
||||
* Worker function for creating a DirectSound buffer.
|
||||
*/
|
||||
static LPDIRECTSOUNDBUFFER create_dsound_buffer(int len, int freq, int bits, int stereo, int vol)
|
||||
{
|
||||
LPDIRECTSOUNDBUFFER snd_buf;
|
||||
WAVEFORMATEX wf;
|
||||
DSBUFFERDESC dsbdesc;
|
||||
HRESULT hr;
|
||||
|
||||
/* setup wave format structure */
|
||||
memset(&wf, 0, sizeof(WAVEFORMATEX));
|
||||
wf.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wf.nChannels = stereo ? 2 : 1;
|
||||
wf.nSamplesPerSec = freq;
|
||||
wf.wBitsPerSample = bits;
|
||||
wf.nBlockAlign = bits * (stereo ? 2 : 1) / 8;
|
||||
wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
|
||||
|
||||
/* setup DSBUFFERDESC structure */
|
||||
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
|
||||
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
|
||||
|
||||
/* need volume control and global focus */
|
||||
dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS |
|
||||
DSBCAPS_GETCURRENTPOSITION2;
|
||||
|
||||
dsbdesc.dwBufferBytes = len * (bits / 8) * (stereo ? 2 : 1);
|
||||
dsbdesc.lpwfxFormat = &wf;
|
||||
|
||||
/* create buffer */
|
||||
hr = IDirectSound_CreateSoundBuffer(directsound, &dsbdesc, &snd_buf, NULL);
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "create_directsound_buffer() failed (%s).\n", ds_err(hr));
|
||||
_TRACE(PREFIX_E " - %d Hz, %s, %d bits\n", freq, stereo ? "stereo" : "mono", bits);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* set volume */
|
||||
IDirectSoundBuffer_SetVolume(snd_buf, alleg_to_dsound_volume[CLAMP(0, vol, 255)]);
|
||||
|
||||
return snd_buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_dsoundmix_mixer_callback:
|
||||
* Callback function to update sound in the DS buffer.
|
||||
*/
|
||||
static void digi_dsoundmix_mixer_callback(void)
|
||||
{
|
||||
LPVOID lpvPtr1, lpvPtr2;
|
||||
DWORD dwBytes1, dwBytes2;
|
||||
DWORD playcurs, writecurs;
|
||||
HRESULT hr;
|
||||
int switch_mode;
|
||||
|
||||
/* handle display switchs */
|
||||
switch_mode = get_display_switch_mode();
|
||||
|
||||
if (alleg_buf_paused) {
|
||||
if (_win_app_foreground ||
|
||||
(switch_mode == SWITCH_BACKGROUND) || (switch_mode == SWITCH_BACKAMNESIA)) {
|
||||
/* get current state of the sound buffer */
|
||||
hr = IDirectSoundBuffer_GetStatus(alleg_buf, &dwBytes1);
|
||||
if ((hr == DS_OK) && (dwBytes1 & DSBSTATUS_BUFFERLOST)) {
|
||||
if(IDirectSoundBuffer_Restore(alleg_buf) != DS_OK)
|
||||
return;
|
||||
IDirectSoundBuffer_SetVolume(alleg_buf, alleg_buf_vol);
|
||||
}
|
||||
|
||||
alleg_buf_paused = FALSE;
|
||||
IDirectSoundBuffer_Play(alleg_buf, 0, 0, DSBPLAY_LOOPING);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (!_win_app_foreground &&
|
||||
((switch_mode == SWITCH_PAUSE) || (switch_mode == SWITCH_AMNESIA))) {
|
||||
alleg_buf_paused = TRUE;
|
||||
IDirectSoundBuffer_Stop(alleg_buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if USE_NEW_CODE /* this should work, dammit */
|
||||
/* write data into the buffer */
|
||||
if (digidsbufdirty) {
|
||||
_mix_some_samples((uintptr_t)digidsbufdata, 0, TRUE);
|
||||
digidsbufdirty = FALSE;
|
||||
}
|
||||
|
||||
hr = IDirectSoundBuffer_GetCurrentPosition(alleg_buf, &playcurs, &writecurs);
|
||||
if (FAILED(hr))
|
||||
return;
|
||||
|
||||
if (((playcurs-writecurs)%(digidsbufsize*2)) < digidsbufsize)
|
||||
return;
|
||||
|
||||
/* Consider the buffer used. Even if the buffer was lost, mark the data as old
|
||||
so the mixer doesn't stall */
|
||||
digidsbufdirty = TRUE;
|
||||
|
||||
hr = IDirectSoundBuffer_Lock(alleg_buf, 0, digidsbufsize,
|
||||
&lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2,
|
||||
DSBLOCK_FROMWRITECURSOR);
|
||||
|
||||
/* only try to restore the buffer once. don't wait around forever */
|
||||
if (hr == DSERR_BUFFERLOST) {
|
||||
if(IDirectSoundBuffer_Restore(alleg_buf) != DS_OK)
|
||||
return;
|
||||
|
||||
IDirectSoundBuffer_Play(alleg_buf, 0, 0, DSBPLAY_LOOPING);
|
||||
IDirectSoundBuffer_SetVolume(alleg_buf, alleg_buf_vol);
|
||||
hr = IDirectSoundBuffer_Lock(alleg_buf, 0, digidsbufsize,
|
||||
&lpvPtr1, &dwBytes1, &lpvPtr2, &dwBytes2,
|
||||
DSBLOCK_FROMWRITECURSOR);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
return;
|
||||
|
||||
/* if the first buffer has enough room, put it all there */
|
||||
if(dwBytes1 >= digidsbufsize) {
|
||||
dwBytes1 = digidsbufsize;
|
||||
memcpy(lpvPtr1, digidsbufdata, dwBytes1);
|
||||
dwBytes2 = 0;
|
||||
}
|
||||
/* else, sput the first part into the first buffer, and the rest into the
|
||||
second */
|
||||
else {
|
||||
memcpy(lpvPtr1, digidsbufdata, dwBytes1);
|
||||
dwBytes2 = digidsbufsize-dwBytes1;
|
||||
memcpy(lpvPtr2, digidsbufdata+dwBytes1, dwBytes2);
|
||||
}
|
||||
|
||||
IDirectSoundBuffer_Unlock(alleg_buf, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
|
||||
#else
|
||||
hr = IDirectSoundBuffer_GetCurrentPosition(alleg_buf, &playcurs, &writecurs);
|
||||
if (FAILED(hr))
|
||||
return;
|
||||
|
||||
writecurs /= (digidsbufsize/bufdivs);
|
||||
writecurs += 8;
|
||||
|
||||
while (writecurs > (bufdivs-1))
|
||||
writecurs -= bufdivs;
|
||||
|
||||
/* avoid locking the buffer if no data to write */
|
||||
if (writecurs == digidsbufpos)
|
||||
return;
|
||||
|
||||
hr = IDirectSoundBuffer_Lock(alleg_buf, 0, 0,
|
||||
&lpvPtr1, &dwBytes1,
|
||||
&lpvPtr2, &dwBytes2,
|
||||
DSBLOCK_FROMWRITECURSOR | DSBLOCK_ENTIREBUFFER);
|
||||
|
||||
if (FAILED(hr))
|
||||
return;
|
||||
|
||||
/* write data into the buffer */
|
||||
while (writecurs != digidsbufpos) {
|
||||
if (lpvPtr2) {
|
||||
memcpy((char*)lpvPtr2 + (((dwBytes1+dwBytes2)/bufdivs)*digidsbufpos),
|
||||
digidsbufdata + (((dwBytes1+dwBytes2)/bufdivs)*digidsbufpos),
|
||||
(dwBytes1+dwBytes2)/bufdivs);
|
||||
}
|
||||
else {
|
||||
memcpy((char*)lpvPtr1 + (((dwBytes1)/bufdivs)*digidsbufpos),
|
||||
digidsbufdata + (((dwBytes1)/bufdivs)*digidsbufpos),
|
||||
(dwBytes1)/bufdivs);
|
||||
}
|
||||
|
||||
if (++digidsbufpos > (bufdivs-1))
|
||||
digidsbufpos = 0;
|
||||
|
||||
_mix_some_samples((uintptr_t) (digidsbufdata+(((dwBytes1+dwBytes2)/bufdivs)*digidsbufpos)), 0, TRUE);
|
||||
}
|
||||
|
||||
IDirectSoundBuffer_Unlock(alleg_buf, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_dsoundmix_detect:
|
||||
*/
|
||||
static int digi_dsoundmix_detect(int input)
|
||||
{
|
||||
HRESULT hr;
|
||||
int id;
|
||||
|
||||
/* deduce our device number from the driver ID code */
|
||||
id = ((digi_driver->id >> 8) & 0xFF) - 'A';
|
||||
|
||||
if (input)
|
||||
return digi_directsound_capture_detect(driver_guids[id]);
|
||||
|
||||
if (!directsound) {
|
||||
/* initialize DirectSound interface */
|
||||
hr = DirectSoundCreate(driver_guids[id], &directsound, NULL);
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "DirectSound interface creation failed during detect (%s)\n", ds_err(hr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
_TRACE(PREFIX_I "DirectSound interface successfully created\n");
|
||||
|
||||
/* release DirectSound */
|
||||
IDirectSound_Release(directsound);
|
||||
directsound = NULL;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_dsoundmix_init:
|
||||
*/
|
||||
static int digi_dsoundmix_init(int input, int voices)
|
||||
{
|
||||
LPVOID lpvPtr1, lpvPtr2;
|
||||
DWORD dwBytes1, dwBytes2;
|
||||
HRESULT hr;
|
||||
DSCAPS dscaps;
|
||||
DSBUFFERDESC desc;
|
||||
WAVEFORMATEX format;
|
||||
HWND allegro_wnd = win_get_window();
|
||||
char tmp1[128], tmp2[128];
|
||||
int v, id;
|
||||
|
||||
/* deduce our device number from the driver ID code */
|
||||
id = ((digi_driver->id >> 8) & 0xFF) - 'A';
|
||||
|
||||
if (input)
|
||||
return digi_directsound_capture_init(driver_guids[id]);
|
||||
|
||||
digi_driver->voices = voices;
|
||||
|
||||
/* initialize DirectSound interface */
|
||||
hr = DirectSoundCreate(driver_guids[id], &directsound, NULL);
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "Can't create DirectSound interface (%s)\n", ds_err(hr));
|
||||
goto Error;
|
||||
}
|
||||
|
||||
/* set cooperative level */
|
||||
hr = IDirectSound_SetCooperativeLevel(directsound, allegro_wnd, DSSCL_PRIORITY);
|
||||
if (FAILED(hr))
|
||||
_TRACE(PREFIX_W "Can't set DirectSound cooperative level (%s)\n", ds_err(hr));
|
||||
else
|
||||
_TRACE(PREFIX_I "DirectSound cooperation level set to DSSCL_PRIORITY\n");
|
||||
|
||||
/* get hardware capabilities */
|
||||
dscaps.dwSize = sizeof(DSCAPS);
|
||||
hr = IDirectSound_GetCaps(directsound, &dscaps);
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "Can't get DirectSound caps (%s)\n", ds_err(hr));
|
||||
goto Error;
|
||||
}
|
||||
|
||||
/* For some reason the audio driver on my machine doesn't seem to set either
|
||||
* PRIMARY16BIT or PRIMARY8BIT; of course it actually does support 16-bit
|
||||
* sound.
|
||||
*/
|
||||
if (((dscaps.dwFlags & DSCAPS_PRIMARY16BIT) || !(dscaps.dwFlags & DSCAPS_PRIMARY8BIT))
|
||||
&& ((_sound_bits >= 16) || (_sound_bits <= 0)))
|
||||
_bits = 16;
|
||||
else
|
||||
_bits = 8;
|
||||
|
||||
if ((dscaps.dwFlags & DSCAPS_PRIMARYSTEREO) && _sound_stereo)
|
||||
_stereo = 1;
|
||||
else
|
||||
_stereo = 0;
|
||||
|
||||
/* Try to set the requested frequency */
|
||||
if ((dscaps.dwMaxSecondarySampleRate > (DWORD)_sound_freq) && (_sound_freq > 0))
|
||||
_freq = _sound_freq;
|
||||
/* If no frequency is specified, make sure it's clamped to a reasonable value
|
||||
by default */
|
||||
else if ((_sound_freq <= 0) && (dscaps.dwMaxSecondarySampleRate > 44100))
|
||||
_freq = 44100;
|
||||
else
|
||||
_freq = dscaps.dwMaxSecondarySampleRate;
|
||||
|
||||
_TRACE(PREFIX_I "DirectSound caps: %u bits, %s, %uHz\n", _bits, _stereo ? "stereo" : "mono", _freq);
|
||||
|
||||
memset(&desc, 0, sizeof(DSBUFFERDESC));
|
||||
desc.dwSize = sizeof(DSBUFFERDESC);
|
||||
desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GLOBALFOCUS;// | DSBCAPS_CTRLVOLUME | DSBCAPS_STICKYFOCUS;
|
||||
|
||||
hr = IDirectSound_CreateSoundBuffer(directsound, &desc, &prim_buf, NULL);
|
||||
if (FAILED(hr))
|
||||
_TRACE(PREFIX_W "Can't create primary buffer (%s)\nGlobal volume control won't be available\n", ds_err(hr));
|
||||
|
||||
if (prim_buf) {
|
||||
hr = IDirectSoundBuffer_GetFormat(prim_buf, &format, sizeof(format), NULL);
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_W "Can't get primary buffer format (%s)\n", ds_err(hr));
|
||||
}
|
||||
else {
|
||||
format.nChannels = (_stereo ? 2 : 1);
|
||||
format.nSamplesPerSec = _freq;
|
||||
format.wBitsPerSample = _bits;
|
||||
format.nBlockAlign = (format.wBitsPerSample * format.nChannels) >> 3;
|
||||
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
|
||||
|
||||
hr = IDirectSoundBuffer_SetFormat(prim_buf, &format);
|
||||
if (FAILED(hr))
|
||||
_TRACE(PREFIX_W "Can't set primary buffer format (%s)\n", ds_err(hr));
|
||||
|
||||
hr = IDirectSoundBuffer_GetFormat(prim_buf, &format, sizeof(format), NULL);
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_W "Can't get primary buffer format (%s)\n", ds_err(hr));
|
||||
}
|
||||
else {
|
||||
_TRACE(PREFIX_I "primary format:\n");
|
||||
_TRACE(PREFIX_I " %u channels\n %u Hz\n %u AvgBytesPerSec\n %u BlockAlign\n %u bits\n %u size\n",
|
||||
format.nChannels, format.nSamplesPerSec, format.nAvgBytesPerSec,
|
||||
format.nBlockAlign, format.wBitsPerSample, format.cbSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* setup volume lookup table */
|
||||
alleg_to_dsound_volume[0] = DSBVOLUME_MIN;
|
||||
for (v = 1; v < 256; v++) {
|
||||
int dB = DSBVOLUME_MAX + 2000.0*log10(v/255.0);
|
||||
alleg_to_dsound_volume[v] = MAX(DSBVOLUME_MIN, dB);
|
||||
}
|
||||
|
||||
/* create the sound buffer to mix into */
|
||||
alleg_buf = create_dsound_buffer(get_config_int(uconvert_ascii("sound", tmp1),
|
||||
uconvert_ascii("dsound_numfrags", tmp2),
|
||||
6) * 1024,
|
||||
_freq, _bits, _stereo, 255);
|
||||
if(!alleg_buf) {
|
||||
_TRACE(PREFIX_E "Can't create mixing buffer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* fill the sound buffer with zeros */
|
||||
hr = IDirectSoundBuffer_Lock(alleg_buf, 0, 0, &lpvPtr1, &dwBytes1,
|
||||
&lpvPtr2, &dwBytes2, DSBLOCK_ENTIREBUFFER);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
_TRACE(PREFIX_E "Can't lock sound buffer (%s)\n", ds_err(hr));
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(lpvPtr1, 0, dwBytes1);
|
||||
digidsbufsize = dwBytes1;
|
||||
|
||||
if (lpvPtr2) {
|
||||
_TRACE(PREFIX_E "Second buffer set when locking buffer. Error?\n");
|
||||
memset(lpvPtr2, 0, dwBytes2);
|
||||
digidsbufsize += dwBytes2;
|
||||
}
|
||||
|
||||
IDirectSoundBuffer_Unlock(alleg_buf, lpvPtr1, dwBytes1, lpvPtr2, dwBytes2);
|
||||
|
||||
_TRACE(PREFIX_I "Sound buffer length is %u\n", digidsbufsize);
|
||||
|
||||
/* shouldn't ever happen */
|
||||
if (digidsbufsize&1023) {
|
||||
_TRACE(PREFIX_E "Sound buffer is not multiple of 1024, failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if USE_NEW_CODE
|
||||
digidsbufsize /= 2;
|
||||
#endif
|
||||
digidsbufdata = _AL_MALLOC_ATOMIC(digidsbufsize);
|
||||
if (!digidsbufdata) {
|
||||
_TRACE(PREFIX_E "Can't create temp buffer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if USE_NEW_CODE
|
||||
if (_mixer_init(digidsbufsize / (_bits /8), _freq, _stereo,
|
||||
((_bits == 16) ? 1 : 0), &digi_driver->voices) != 0) {
|
||||
_TRACE(PREFIX_E "Can't init software mixer\n");
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
bufdivs = digidsbufsize/1024;
|
||||
if (_mixer_init((digidsbufsize / (_bits /8)) / bufdivs, _freq,
|
||||
_stereo, ((_bits == 16) ? 1 : 0), &digi_driver->voices) != 0) {
|
||||
_TRACE(PREFIX_E "Can't init software mixer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
_mix_some_samples((uintptr_t)digidsbufdata, 0, TRUE);
|
||||
#endif
|
||||
|
||||
/* get primary buffer volume */
|
||||
IDirectSoundBuffer_GetVolume(alleg_buf, &initial_volume);
|
||||
alleg_buf_vol = initial_volume;
|
||||
|
||||
/* mark the buffer as paused, so the mixer callback will start it */
|
||||
alleg_buf_paused = TRUE;
|
||||
#if USE_NEW_CODE
|
||||
digidsbufdirty = TRUE;
|
||||
#endif
|
||||
install_int(digi_dsoundmix_mixer_callback, 20); /* 50 Hz */
|
||||
|
||||
return 0;
|
||||
|
||||
Error:
|
||||
_TRACE(PREFIX_E "digi_directsound_init() failed\n");
|
||||
digi_dsoundmix_exit(0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_dsoundmix_exit:
|
||||
*/
|
||||
static void digi_dsoundmix_exit(int input)
|
||||
{
|
||||
if (input) {
|
||||
digi_directsound_capture_exit();
|
||||
return;
|
||||
}
|
||||
|
||||
/* stop playing */
|
||||
remove_int(digi_dsoundmix_mixer_callback);
|
||||
|
||||
if (digidsbufdata) {
|
||||
_AL_FREE(digidsbufdata);
|
||||
digidsbufdata = NULL;
|
||||
}
|
||||
|
||||
/* destroy mixer buffer */
|
||||
if (alleg_buf) {
|
||||
IDirectSoundBuffer_Release(alleg_buf);
|
||||
alleg_buf = NULL;
|
||||
}
|
||||
|
||||
/* destroy primary buffer */
|
||||
if (prim_buf) {
|
||||
/* restore primary buffer initial volume */
|
||||
IDirectSoundBuffer_SetVolume(prim_buf, initial_volume);
|
||||
|
||||
IDirectSoundBuffer_Release(prim_buf);
|
||||
prim_buf = NULL;
|
||||
}
|
||||
|
||||
/* shutdown DirectSound */
|
||||
if (directsound) {
|
||||
IDirectSound_Release(directsound);
|
||||
directsound = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_dsoundmix_set_mixer_volume:
|
||||
*/
|
||||
static int digi_dsoundmix_set_mixer_volume(int volume)
|
||||
{
|
||||
if (prim_buf) {
|
||||
alleg_buf_vol = alleg_to_dsound_volume[CLAMP(0, volume, 255)];
|
||||
IDirectSoundBuffer_SetVolume(alleg_buf, alleg_buf_vol);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_dsoundmix_get_mixer_volume:
|
||||
*/
|
||||
static int digi_dsoundmix_get_mixer_volume(void)
|
||||
{
|
||||
LONG vol;
|
||||
|
||||
if (!prim_buf)
|
||||
return -1;
|
||||
|
||||
IDirectSoundBuffer_GetVolume(alleg_buf, &vol);
|
||||
vol = CLAMP(0, pow(10, (vol/2000.0))*255.0 - DSBVOLUME_MAX, 255);
|
||||
|
||||
return vol;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_dsoundmix_buffer_size:
|
||||
*/
|
||||
static int digi_dsoundmix_buffer_size(void)
|
||||
{
|
||||
return digidsbufsize / (_bits / 8) / (_stereo ? 2 : 1);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,365 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* Windows midi driver.
|
||||
*
|
||||
* By Stefan Schimanski.
|
||||
*
|
||||
* Midi input added by Daniel Verkamp.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#include "allegro.h"
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintwin.h"
|
||||
|
||||
#ifndef SCAN_DEPEND
|
||||
#ifdef ALLEGRO_MINGW32
|
||||
#undef MAKEFOURCC
|
||||
#endif
|
||||
|
||||
#include <mmsystem.h>
|
||||
|
||||
#ifdef ALLEGRO_MSVC
|
||||
#include <mmreg.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ALLEGRO_WINDOWS
|
||||
#error something is wrong with the makefile
|
||||
#endif
|
||||
|
||||
#define PREFIX_I "al-wmidi INFO: "
|
||||
#define PREFIX_W "al-wmidi WARNING: "
|
||||
#define PREFIX_E "al-wmidi ERROR: "
|
||||
|
||||
|
||||
int midi_win32_detect(int input);
|
||||
int midi_win32_init(int input, int voices);
|
||||
void midi_win32_exit(int input);
|
||||
int midi_win32_set_mixer_volume(int volume);
|
||||
int midi_win32_get_mixer_volume(void);
|
||||
void midi_win32_raw_midi(int data);
|
||||
|
||||
int midi_win32_in_detect(int input);
|
||||
int midi_win32_in_init(int input, int voices);
|
||||
void midi_win32_in_exit(int input);
|
||||
static void CALLBACK midi_in_proc(HMIDIIN, UINT, DWORD, DWORD, DWORD);
|
||||
|
||||
|
||||
/* driver globals */
|
||||
static HMIDIOUT midi_device = NULL;
|
||||
static HMIDIIN midi_in_device = NULL;
|
||||
|
||||
|
||||
/* dynamically generated driver list */
|
||||
static _DRIVER_INFO *driver_list = NULL;
|
||||
|
||||
|
||||
/* MIDI recording callback */
|
||||
static void CALLBACK midi_in_proc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance,
|
||||
DWORD dwParam1, DWORD dwParam2)
|
||||
{
|
||||
if ((midi_in_device == NULL) || (midi_recorder == NULL)) return;
|
||||
midi_recorder((unsigned char)(dwParam1 & 0xff)); /* status byte */
|
||||
midi_recorder((unsigned char)((dwParam1 >> 8) & 0xff)); /* data byte 1 */
|
||||
midi_recorder((unsigned char)((dwParam1 >> 16) & 0xff)); /* data byte 2 */
|
||||
}
|
||||
|
||||
|
||||
/* _get_win_midi_driver_list:
|
||||
* System driver hook for listing the available MIDI drivers. This generates
|
||||
* the device list at runtime, to match whatever Windows devices are
|
||||
* available.
|
||||
*/
|
||||
_DRIVER_INFO *_get_win_midi_driver_list(void)
|
||||
{
|
||||
MIDI_DRIVER *driver;
|
||||
MIDIOUTCAPS caps;
|
||||
MIDIINCAPS caps_in;
|
||||
int num_drivers, i;
|
||||
|
||||
if (!driver_list) {
|
||||
num_drivers = midiOutGetNumDevs();
|
||||
|
||||
/* include the MIDI mapper (id == -1) */
|
||||
if (num_drivers)
|
||||
num_drivers++;
|
||||
|
||||
driver_list = _create_driver_list();
|
||||
|
||||
/* MidiOut drivers */
|
||||
for (i=0; i<num_drivers; i++) {
|
||||
driver = _AL_MALLOC(sizeof(MIDI_DRIVER));
|
||||
memcpy(driver, &_midi_none, sizeof(MIDI_DRIVER));
|
||||
|
||||
if (i == 0)
|
||||
driver->id = MIDI_WIN32MAPPER;
|
||||
else
|
||||
driver->id = MIDI_WIN32(i-1);
|
||||
|
||||
midiOutGetDevCaps(i-1, &caps, sizeof(caps));
|
||||
|
||||
driver->ascii_name = strdup(caps.szPname);
|
||||
|
||||
driver->detect = midi_win32_detect;
|
||||
driver->init = midi_win32_init;
|
||||
driver->exit = midi_win32_exit;
|
||||
driver->set_mixer_volume = midi_win32_set_mixer_volume;
|
||||
driver->get_mixer_volume = midi_win32_get_mixer_volume;
|
||||
driver->raw_midi = midi_win32_raw_midi;
|
||||
|
||||
_driver_list_append_driver(&driver_list, driver->id, driver, TRUE);
|
||||
}
|
||||
|
||||
/* MidiIn drivers */
|
||||
num_drivers = midiInGetNumDevs();
|
||||
for (i=0; i<num_drivers; i++) {
|
||||
driver = _AL_MALLOC(sizeof(MIDI_DRIVER));
|
||||
memcpy(driver, &_midi_none, sizeof(MIDI_DRIVER));
|
||||
|
||||
driver->id = MIDI_WIN32_IN(i); /* added MIDI_WIN32_IN to alwin.h */
|
||||
|
||||
midiInGetDevCaps(i, &caps_in, sizeof(caps_in));
|
||||
|
||||
driver->ascii_name = strdup(caps_in.szPname);
|
||||
|
||||
driver->detect = midi_win32_in_detect;
|
||||
driver->init = midi_win32_in_init;
|
||||
driver->exit = midi_win32_in_exit;
|
||||
|
||||
_driver_list_append_driver(&driver_list, driver->id, driver, TRUE);
|
||||
}
|
||||
|
||||
/* cross-platform DIGital MIDi driver */
|
||||
_driver_list_append_driver(&driver_list, MIDI_DIGMID, &midi_digmid, TRUE);
|
||||
}
|
||||
|
||||
return driver_list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _free_win_midi_driver_list:
|
||||
* Helper function for freeing the dynamically generated driver list.
|
||||
*/
|
||||
void _free_win_midi_driver_list(void)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (driver_list) {
|
||||
while (driver_list[i].driver) {
|
||||
if (driver_list[i].id != MIDI_DIGMID) {
|
||||
_AL_FREE((char*)((MIDI_DRIVER*)driver_list[i].driver)->ascii_name);
|
||||
_AL_FREE(driver_list[i].driver);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
_destroy_driver_list(driver_list);
|
||||
driver_list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* midi_win32_detect:
|
||||
*/
|
||||
int midi_win32_detect(int input)
|
||||
{
|
||||
/* the input drivers are separate from the output drivers */
|
||||
if (input)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* midi_win32_in_detect:
|
||||
*/
|
||||
int midi_win32_in_detect(int input)
|
||||
{
|
||||
if (input)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* midi_win32_init:
|
||||
*/
|
||||
int midi_win32_init(int input, int voices)
|
||||
{
|
||||
MMRESULT hr;
|
||||
int id;
|
||||
|
||||
/* deduce our device number from the driver ID code */
|
||||
if ((midi_driver->id & 0xFF) == 'M')
|
||||
/* we are using the midi mapper (driver id is WIN32M) */
|
||||
id = MIDI_MAPPER;
|
||||
else
|
||||
/* actual driver */
|
||||
id = (midi_driver->id & 0xFF) - 'A';
|
||||
|
||||
/* open midi mapper */
|
||||
hr = midiOutOpen(&midi_device, id, 0, 0, CALLBACK_NULL);
|
||||
if (hr != MMSYSERR_NOERROR) {
|
||||
_TRACE(PREFIX_E "midiOutOpen failed (%x)\n", hr);
|
||||
goto Error;
|
||||
}
|
||||
|
||||
/* resets midi mapper */
|
||||
midiOutReset(midi_device);
|
||||
|
||||
return 0;
|
||||
|
||||
Error:
|
||||
midi_win32_exit(input);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* midi_win32_in_init:
|
||||
*/
|
||||
int midi_win32_in_init(int input, int voices)
|
||||
{
|
||||
MMRESULT hr;
|
||||
int id;
|
||||
|
||||
/* deduce our device number from the driver ID code */
|
||||
id = (midi_input_driver->id & 0xFF) - 'A';
|
||||
|
||||
/* open midi input device */
|
||||
hr = midiInOpen(&midi_in_device, id, (DWORD)midi_in_proc,
|
||||
(DWORD)NULL, CALLBACK_FUNCTION);
|
||||
if (hr != MMSYSERR_NOERROR) {
|
||||
_TRACE(PREFIX_E "midiInOpen failed (%x)\n", hr);
|
||||
midi_win32_in_exit(input);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
midiInReset(midi_in_device);
|
||||
midiInStart(midi_in_device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* midi_win32_exit:
|
||||
*/
|
||||
void midi_win32_exit(int input)
|
||||
{
|
||||
/* close midi stream and release device */
|
||||
if (midi_device != NULL) {
|
||||
midiOutReset(midi_device);
|
||||
|
||||
midiOutClose(midi_device);
|
||||
midi_device = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* midi_win32_in_exit:
|
||||
*/
|
||||
void midi_win32_in_exit(int input)
|
||||
{
|
||||
if (midi_in_device != NULL) {
|
||||
midiInStop(midi_in_device);
|
||||
midiInReset(midi_in_device);
|
||||
midiInClose(midi_in_device);
|
||||
midi_in_device = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* midi_win32_set_mixer_volume:
|
||||
*/
|
||||
int midi_win32_set_mixer_volume(int volume)
|
||||
{
|
||||
unsigned long win32_midi_vol = (volume << 8) + (volume << 24);
|
||||
midiOutSetVolume(midi_device, win32_midi_vol);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* midi_win32_get_mixer_volume:
|
||||
*/
|
||||
int midi_win32_get_mixer_volume(void)
|
||||
{
|
||||
DWORD vol;
|
||||
|
||||
if (!midi_device)
|
||||
return -1;
|
||||
|
||||
if (midiOutGetVolume(midi_device, &vol) != MMSYSERR_NOERROR)
|
||||
return -1;
|
||||
|
||||
vol &= 0xffff;
|
||||
return vol / (0xffff / 255);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* midi_switch_out:
|
||||
*/
|
||||
void midi_switch_out(void)
|
||||
{
|
||||
if (midi_device)
|
||||
midiOutReset(midi_device);
|
||||
}
|
||||
|
||||
|
||||
/* midi_win32_raw_midi:
|
||||
*/
|
||||
void midi_win32_raw_midi(int data)
|
||||
{
|
||||
static int msg_lengths[8] =
|
||||
{3, 3, 3, 3, 2, 2, 3, 0};
|
||||
static unsigned long midi_msg;
|
||||
static int midi_msg_len;
|
||||
static int midi_msg_pos;
|
||||
|
||||
if (data >= 0x80) {
|
||||
midi_msg_len = msg_lengths[(data >> 4) & 0x07];
|
||||
midi_msg = 0;
|
||||
midi_msg_pos = 0;
|
||||
}
|
||||
|
||||
if (midi_msg_len > 0) {
|
||||
midi_msg |= ((unsigned long)data) << (midi_msg_pos * 8);
|
||||
midi_msg_pos++;
|
||||
|
||||
if (midi_msg_pos == midi_msg_len) {
|
||||
if (midi_device != NULL) {
|
||||
switch (get_display_switch_mode()) {
|
||||
case SWITCH_AMNESIA:
|
||||
case SWITCH_PAUSE:
|
||||
if (_win_app_foreground)
|
||||
midiOutShortMsg(midi_device, midi_msg);
|
||||
else
|
||||
midiOutReset(midi_device);
|
||||
break;
|
||||
default:
|
||||
midiOutShortMsg(midi_device, midi_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* List of Windows sound drivers, kept in a seperate file so that
|
||||
* they can be overriden by user programs.
|
||||
*
|
||||
* By Shawn Hargreaves.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#include "allegro.h"
|
||||
|
||||
#ifndef ALLEGRO_WINDOWS
|
||||
#error something is wrong with the makefile
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
BEGIN_DIGI_DRIVER_LIST
|
||||
/* nothing here: the driver list is dynamically generated */
|
||||
END_DIGI_DRIVER_LIST
|
||||
|
||||
|
||||
BEGIN_MIDI_DRIVER_LIST
|
||||
/* nothing here: the driver list is dynamically generated */
|
||||
END_MIDI_DRIVER_LIST
|
@ -1,402 +0,0 @@
|
||||
/* ______ ___ ___
|
||||
* /\ _ \ /\_ \ /\_ \
|
||||
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
|
||||
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
|
||||
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
|
||||
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
|
||||
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
|
||||
* /\____/
|
||||
* \_/__/
|
||||
*
|
||||
* Allegro mixer to WaveOut driver.
|
||||
*
|
||||
* By Robin Burrows.
|
||||
*
|
||||
* Based on original src/unix/uoss.c by Joshua Heyer.
|
||||
*
|
||||
* See readme.txt for copyright information.
|
||||
*/
|
||||
|
||||
|
||||
#include "allegro.h"
|
||||
#include "allegro/internal/aintern.h"
|
||||
#include "allegro/platform/aintwin.h"
|
||||
|
||||
#ifndef SCAN_DEPEND
|
||||
#ifdef ALLEGRO_MINGW32
|
||||
#undef MAKEFOURCC
|
||||
#endif
|
||||
|
||||
#include <mmsystem.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef ALLEGRO_MSVC
|
||||
#include <mmreg.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ALLEGRO_WINDOWS
|
||||
#error something is wrong with the makefile
|
||||
#endif
|
||||
|
||||
#define PREFIX_I "al-wsnd INFO: "
|
||||
#define PREFIX_W "al-wsnd WARNING: "
|
||||
#define PREFIX_E "al-wsnd ERROR: "
|
||||
|
||||
|
||||
static int digi_waveout_detect(int input);
|
||||
static int digi_waveout_init(int input, int voices);
|
||||
static void digi_waveout_exit(int input);
|
||||
static int digi_waveout_set_mixer_volume(int volume);
|
||||
static int digi_waveout_get_mixer_volume(void);
|
||||
static int digi_waveout_buffer_size(void);
|
||||
|
||||
|
||||
/* template driver: will be cloned for each device */
|
||||
static DIGI_DRIVER digi_waveout =
|
||||
{
|
||||
0,
|
||||
empty_string,
|
||||
empty_string,
|
||||
empty_string,
|
||||
0, // available voices
|
||||
0, // voice number offset
|
||||
MIXER_MAX_SFX, // maximum voices we can support
|
||||
MIXER_DEF_SFX, // default number of voices to use
|
||||
|
||||
/* setup routines */
|
||||
digi_waveout_detect,
|
||||
digi_waveout_init,
|
||||
digi_waveout_exit,
|
||||
digi_waveout_set_mixer_volume,
|
||||
digi_waveout_get_mixer_volume,
|
||||
|
||||
/* audiostream locking functions */
|
||||
NULL, // AL_METHOD(void *, lock_voice, (int voice, int start, int end));
|
||||
NULL, // AL_METHOD(void, unlock_voice, (int voice));
|
||||
digi_waveout_buffer_size,
|
||||
|
||||
/* voice control functions */
|
||||
_mixer_init_voice,
|
||||
_mixer_release_voice,
|
||||
_mixer_start_voice,
|
||||
_mixer_stop_voice,
|
||||
_mixer_loop_voice,
|
||||
|
||||
/* position control functions */
|
||||
_mixer_get_position,
|
||||
_mixer_set_position,
|
||||
|
||||
/* volume control functions */
|
||||
_mixer_get_volume,
|
||||
_mixer_set_volume,
|
||||
_mixer_ramp_volume,
|
||||
_mixer_stop_volume_ramp,
|
||||
|
||||
/* pitch control functions */
|
||||
_mixer_get_frequency,
|
||||
_mixer_set_frequency,
|
||||
_mixer_sweep_frequency,
|
||||
_mixer_stop_frequency_sweep,
|
||||
|
||||
/* pan control functions */
|
||||
_mixer_get_pan,
|
||||
_mixer_set_pan,
|
||||
_mixer_sweep_pan,
|
||||
_mixer_stop_pan_sweep,
|
||||
|
||||
/* effect control functions */
|
||||
_mixer_set_echo,
|
||||
_mixer_set_tremolo,
|
||||
_mixer_set_vibrato,
|
||||
|
||||
/* input functions */
|
||||
0, // int rec_cap_bits;
|
||||
0, // int rec_cap_stereo;
|
||||
NULL, // AL_METHOD(int, rec_cap_rate, (int bits, int stereo));
|
||||
NULL, // AL_METHOD(int, rec_cap_parm, (int rate, int bits, int stereo));
|
||||
NULL, // AL_METHOD(int, rec_source, (int source));
|
||||
NULL, // AL_METHOD(int, rec_start, (int rate, int bits, int stereo));
|
||||
NULL, // AL_METHOD(void, rec_stop, (void));
|
||||
NULL // AL_METHOD(int, rec_read, (void *buf));
|
||||
};
|
||||
|
||||
|
||||
/* sound driver globals */
|
||||
static HWAVEOUT hWaveOut = NULL;
|
||||
static LPWAVEHDR lpWaveHdr = NULL;
|
||||
static unsigned long int initial_volume;
|
||||
static int digiwobufsize, digiwobufdivs, digiwobufpos;
|
||||
static char * digiwobufdata = NULL;
|
||||
static int _freq, _bits, _stereo;
|
||||
static int waveout_paused = FALSE;
|
||||
|
||||
|
||||
|
||||
/* _get_woalmix_driver:
|
||||
* System driver hook for listing the available sound drivers. This
|
||||
* generates the device list at runtime, to match whatever WaveOut
|
||||
* devices are available.
|
||||
*/
|
||||
DIGI_DRIVER *_get_woalmix_driver(int num)
|
||||
{
|
||||
DIGI_DRIVER *driver;
|
||||
|
||||
driver = _AL_MALLOC(sizeof(DIGI_DRIVER));
|
||||
if (!driver)
|
||||
return NULL;
|
||||
|
||||
memcpy(driver, &digi_waveout, sizeof(DIGI_DRIVER));
|
||||
|
||||
driver->id = DIGI_WAVOUTID(num);
|
||||
|
||||
if (num == 0)
|
||||
driver->ascii_name = "WaveOut 44100hz 16bit stereo";
|
||||
else
|
||||
driver->ascii_name = "WaveOut 22050hz 8bit mono";
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_waveout_mixer_callback:
|
||||
* Callback function to update sound in WaveOut buffer.
|
||||
*/
|
||||
static void digi_waveout_mixer_callback(void)
|
||||
{
|
||||
MMTIME mmt;
|
||||
MMRESULT mmr;
|
||||
int writecurs;
|
||||
int switch_mode;
|
||||
|
||||
/* handle display switchs */
|
||||
switch_mode = get_display_switch_mode();
|
||||
|
||||
if (waveout_paused) {
|
||||
if (_win_app_foreground ||
|
||||
(switch_mode == SWITCH_BACKGROUND) || (switch_mode == SWITCH_BACKAMNESIA)) {
|
||||
waveout_paused = FALSE;
|
||||
waveOutRestart(hWaveOut);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (!_win_app_foreground &&
|
||||
((switch_mode == SWITCH_PAUSE) || (switch_mode == SWITCH_AMNESIA))) {
|
||||
waveout_paused = TRUE;
|
||||
waveOutPause(hWaveOut);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* get current state of buffer */
|
||||
memset(&mmt, 0, sizeof(MMTIME));
|
||||
mmt.wType = TIME_BYTES;
|
||||
|
||||
mmr = waveOutGetPosition(hWaveOut, &mmt, sizeof(MMTIME));
|
||||
if (mmr != MMSYSERR_NOERROR)
|
||||
return;
|
||||
|
||||
writecurs = (int) mmt.u.cb;
|
||||
|
||||
writecurs /= (digiwobufsize/digiwobufdivs);
|
||||
writecurs += 8;
|
||||
|
||||
while (writecurs > (digiwobufdivs-1))
|
||||
writecurs -= digiwobufdivs;
|
||||
|
||||
/* write data into the buffer */
|
||||
while (writecurs != digiwobufpos) {
|
||||
if (++digiwobufpos > (digiwobufdivs-1))
|
||||
digiwobufpos = 0;
|
||||
|
||||
_mix_some_samples((unsigned long) (digiwobufdata+((digiwobufsize/digiwobufdivs)*digiwobufpos)), 0, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_waveout_detect:
|
||||
*/
|
||||
static int digi_waveout_detect(int input)
|
||||
{
|
||||
if (input)
|
||||
return 0;
|
||||
|
||||
/* always present */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_waveout_init:
|
||||
*/
|
||||
static int digi_waveout_init(int input, int voices)
|
||||
{
|
||||
MMRESULT mmr;
|
||||
WAVEFORMATEX format;
|
||||
int id;
|
||||
|
||||
if (input) {
|
||||
ustrzcpy(allegro_error, ALLEGRO_ERROR_SIZE, get_config_text("Input is not supported"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* deduce our device number from the driver ID code */
|
||||
id = ((digi_driver->id >> 8) & 0xFF) - 'A';
|
||||
|
||||
digi_driver->voices = voices;
|
||||
|
||||
/* get hardware capabilities */
|
||||
digiwobufdivs = 32;
|
||||
digiwobufpos = 0;
|
||||
|
||||
if (id == 0) {
|
||||
_bits = 16;
|
||||
_freq = 44100;
|
||||
_stereo = 1;
|
||||
digiwobufsize = digiwobufdivs * 1024;
|
||||
}
|
||||
else {
|
||||
_bits = 8;
|
||||
_freq = 22050;
|
||||
_stereo = 0;
|
||||
digiwobufsize = digiwobufdivs * 512;
|
||||
}
|
||||
|
||||
digiwobufdata = _AL_MALLOC_ATOMIC(digiwobufsize);
|
||||
if (!digiwobufdata) {
|
||||
_TRACE (PREFIX_E "_AL_MALLOC_ATOMIC() failed\n");
|
||||
goto Error;
|
||||
}
|
||||
|
||||
format.wFormatTag = WAVE_FORMAT_PCM;
|
||||
format.nChannels = _stereo ? 2 : 1;
|
||||
format.nSamplesPerSec = _freq;
|
||||
format.wBitsPerSample = _bits;
|
||||
format.nBlockAlign = (format.wBitsPerSample * format.nChannels) >> 3;
|
||||
format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign;
|
||||
|
||||
mmr = waveOutOpen(&hWaveOut, WAVE_MAPPER, &format, 0, 0, CALLBACK_NULL);
|
||||
if (mmr != MMSYSERR_NOERROR) {
|
||||
_TRACE (PREFIX_E "Can't open WaveOut\n");
|
||||
goto Error;
|
||||
}
|
||||
|
||||
lpWaveHdr = _AL_MALLOC(sizeof(WAVEHDR));
|
||||
lpWaveHdr->lpData = digiwobufdata;
|
||||
lpWaveHdr->dwBufferLength = digiwobufsize;
|
||||
lpWaveHdr->dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
|
||||
lpWaveHdr->dwLoops = 0x7fffffffL;
|
||||
|
||||
mmr = waveOutPrepareHeader(hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
|
||||
if (mmr != MMSYSERR_NOERROR) {
|
||||
_TRACE (PREFIX_E "waveOutPrepareHeader() failed\n");
|
||||
goto Error;
|
||||
}
|
||||
|
||||
mmr = waveOutWrite(hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
|
||||
if (mmr != MMSYSERR_NOERROR) {
|
||||
_TRACE (PREFIX_E "waveOutWrite() failed\n" );
|
||||
goto Error;
|
||||
}
|
||||
|
||||
if (_mixer_init((digiwobufsize / (_bits /8)) / digiwobufdivs, _freq,
|
||||
_stereo, ((_bits == 16) ? 1 : 0), &digi_driver->voices) != 0) {
|
||||
_TRACE(PREFIX_E "Can't init software mixer\n");
|
||||
goto Error;
|
||||
}
|
||||
|
||||
_mix_some_samples((unsigned long) digiwobufdata, 0, TRUE);
|
||||
|
||||
/* get volume */
|
||||
waveOutGetVolume(hWaveOut, &initial_volume);
|
||||
|
||||
/* start playing */
|
||||
install_int(digi_waveout_mixer_callback, 20); /* 50 Hz */
|
||||
|
||||
return 0;
|
||||
|
||||
Error:
|
||||
_TRACE(PREFIX_E "digi_waveout_init() failed\n");
|
||||
digi_waveout_exit(0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_waveout_exit:
|
||||
*/
|
||||
static void digi_waveout_exit(int input)
|
||||
{
|
||||
/* stop playing */
|
||||
remove_int(digi_waveout_mixer_callback);
|
||||
|
||||
if (hWaveOut) {
|
||||
waveOutReset(hWaveOut);
|
||||
|
||||
/* restore initial volume */
|
||||
waveOutSetVolume(hWaveOut, initial_volume);
|
||||
|
||||
waveOutUnprepareHeader(hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
|
||||
waveOutClose(hWaveOut);
|
||||
hWaveOut = NULL;
|
||||
}
|
||||
|
||||
if (lpWaveHdr) {
|
||||
_AL_FREE(lpWaveHdr);
|
||||
lpWaveHdr = NULL;
|
||||
}
|
||||
|
||||
if (digiwobufdata) {
|
||||
_AL_FREE(digiwobufdata);
|
||||
digiwobufdata = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_waveout_set_mixer_volume:
|
||||
*/
|
||||
static int digi_waveout_set_mixer_volume(int volume)
|
||||
{
|
||||
DWORD realvol;
|
||||
|
||||
if (hWaveOut) {
|
||||
realvol = (DWORD) volume;
|
||||
realvol |= realvol<<8;
|
||||
realvol |= realvol<<16;
|
||||
waveOutSetVolume(hWaveOut, realvol);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_waveout_get_mixer_volume:
|
||||
*/
|
||||
static int digi_waveout_get_mixer_volume(void)
|
||||
{
|
||||
DWORD vol;
|
||||
|
||||
if (!hWaveOut)
|
||||
return -1;
|
||||
|
||||
if (waveOutGetVolume(hWaveOut, &vol) != MMSYSERR_NOERROR)
|
||||
return -1;
|
||||
|
||||
vol &= 0xffff;
|
||||
return vol / (0xffff / 255);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* digi_waveout_buffer_size:
|
||||
*/
|
||||
static int digi_waveout_buffer_size(void)
|
||||
{
|
||||
return digiwobufsize / (_bits / 8) / (_stereo ? 2 : 1);
|
||||
}
|
@ -91,8 +91,6 @@ SYSTEM_DRIVER system_directx =
|
||||
sys_directx_lock_mutex,
|
||||
sys_directx_unlock_mutex,
|
||||
NULL, /* AL_METHOD(_DRIVER_INFO *, gfx_drivers, (void)); */
|
||||
_get_win_digi_driver_list, /* AL_METHOD(_DRIVER_INFO *, digi_drivers, (void)); */
|
||||
_get_win_midi_driver_list, /* AL_METHOD(_DRIVER_INFO *, midi_drivers, (void)); */
|
||||
NULL, /* AL_METHOD(_DRIVER_INFO *, keyboard_drivers, (void)); */
|
||||
NULL, /* AL_METHOD(_DRIVER_INFO *, mouse_drivers, (void)); */
|
||||
NULL /* AL_METHOD(_DRIVER_INFO *, timer_drivers, (void)); */
|
||||
@ -214,10 +212,6 @@ static int sys_directx_init(void)
|
||||
*/
|
||||
static void sys_directx_exit(void)
|
||||
{
|
||||
/* free allocated resources */
|
||||
_free_win_digi_driver_list();
|
||||
_free_win_midi_driver_list();
|
||||
|
||||
/* unhook or close window */
|
||||
exit_directx_window();
|
||||
|
||||
|
@ -76,12 +76,6 @@ static UINT msg_suicide = 0;
|
||||
struct WINDOW_MODULES {
|
||||
int keyboard;
|
||||
int mouse;
|
||||
int sound;
|
||||
int digi_card;
|
||||
int midi_card;
|
||||
int sound_input;
|
||||
int digi_input_card;
|
||||
int midi_input_card;
|
||||
};
|
||||
|
||||
/* Used in adjust_window(). */
|
||||
@ -107,12 +101,6 @@ static int init_window_modules(struct WINDOW_MODULES *wm)
|
||||
if (wm->mouse)
|
||||
install_mouse();
|
||||
|
||||
if (wm->sound)
|
||||
install_sound(wm->digi_card, wm->midi_card, NULL);
|
||||
|
||||
if (wm->sound_input)
|
||||
install_sound_input(wm->digi_input_card, wm->midi_input_card);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -122,8 +110,6 @@ static int init_window_modules(struct WINDOW_MODULES *wm)
|
||||
* Removes the modules that depend upon the main window:
|
||||
* - keyboard (DirectInput),
|
||||
* - mouse (DirectInput),
|
||||
* - sound (DirectSound),
|
||||
* - sound input (DirectSoundCapture).
|
||||
* If WM is not NULL, record which modules are really removed.
|
||||
*/
|
||||
static void exit_window_modules(struct WINDOW_MODULES *wm)
|
||||
@ -144,26 +130,6 @@ static void exit_window_modules(struct WINDOW_MODULES *wm)
|
||||
|
||||
remove_mouse();
|
||||
}
|
||||
|
||||
if (_sound_installed) {
|
||||
if (wm) {
|
||||
wm->sound = TRUE;
|
||||
wm->digi_card = digi_card;
|
||||
wm->midi_card = midi_card;
|
||||
}
|
||||
|
||||
remove_sound();
|
||||
}
|
||||
|
||||
if (_sound_input_installed) {
|
||||
if (wm) {
|
||||
wm->sound_input = TRUE;
|
||||
wm->digi_input_card = digi_input_card;
|
||||
wm->midi_input_card = midi_input_card;
|
||||
}
|
||||
|
||||
remove_sound_input();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -45,8 +45,6 @@ static int _xwin_sysdrv_desktop_color_depth(void);
|
||||
static int _xwin_sysdrv_get_desktop_resolution(int *width, int *height);
|
||||
static void _xwin_sysdrv_get_gfx_safe_mode(int *driver, struct GFX_MODE *mode);
|
||||
static _DRIVER_INFO *_xwin_sysdrv_gfx_drivers(void);
|
||||
static _DRIVER_INFO *_xwin_sysdrv_digi_drivers(void);
|
||||
static _DRIVER_INFO *_xwin_sysdrv_midi_drivers(void);
|
||||
static _DRIVER_INFO *_xwin_sysdrv_keyboard_drivers(void);
|
||||
static _DRIVER_INFO *_xwin_sysdrv_mouse_drivers(void);
|
||||
static _DRIVER_INFO *_xwin_sysdrv_timer_drivers(void);
|
||||
@ -95,8 +93,6 @@ SYSTEM_DRIVER system_xwin =
|
||||
NULL, /* unlock_mutex */
|
||||
#endif
|
||||
_xwin_sysdrv_gfx_drivers,
|
||||
_xwin_sysdrv_digi_drivers,
|
||||
_xwin_sysdrv_midi_drivers,
|
||||
_xwin_sysdrv_keyboard_drivers,
|
||||
_xwin_sysdrv_mouse_drivers,
|
||||
_xwin_sysdrv_timer_drivers
|
||||
@ -343,26 +339,6 @@ static _DRIVER_INFO *_xwin_sysdrv_gfx_drivers(void)
|
||||
|
||||
|
||||
|
||||
/* _xwin_sysdrv_digi_drivers:
|
||||
* Get the list of digital sound drivers.
|
||||
*/
|
||||
static _DRIVER_INFO *_xwin_sysdrv_digi_drivers(void)
|
||||
{
|
||||
return _unix_digi_driver_list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _xwin_sysdrv_midi_drivers:
|
||||
* Get the list of MIDI drivers.
|
||||
*/
|
||||
static _DRIVER_INFO *_xwin_sysdrv_midi_drivers(void)
|
||||
{
|
||||
return _unix_midi_driver_list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* _xwin_sysdrv_keyboard_drivers:
|
||||
* Get the list of keyboard drivers.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user