diff options
| author | Nicolas Noble | 2002-05-16 06:46:50 +0000 | 
|---|---|---|
| committer | Nicolas Noble | 2002-05-16 06:46:50 +0000 | 
| commit | 5edf1e6d7f9ca5ce8fa4e6ded69adff61c60ab50 (patch) | |
| tree | cb82f69a3dfa64011f81e85333b5a303261d3c00 | |
| parent | 4f24f91f8c47d2f91233cc41057c808aa3f0df9f (diff) | |
| download | scummvm-rg350-5edf1e6d7f9ca5ce8fa4e6ded69adff61c60ab50.tar.gz scummvm-rg350-5edf1e6d7f9ca5ce8fa4e6ded69adff61c60ab50.tar.bz2 scummvm-rg350-5edf1e6d7f9ca5ce8fa4e6ded69adff61c60ab50.zip | |
Added an ALSA sequencer support. Updated readme.txt to explain it, and
Makefile to allow the user to enable it. I also reorganised the Makefile
a bit, since there is now one more optionnal library. BBrox, I also
merged your Makefile.x11 in it, just take a look at it!
svn-id: r4341
| -rw-r--r-- | Makefile | 36 | ||||
| -rw-r--r-- | gameDetector.cpp | 4 | ||||
| -rw-r--r-- | readme.txt | 48 | ||||
| -rw-r--r-- | sound/mididrv.cpp | 200 | ||||
| -rw-r--r-- | sound/mididrv.h | 4 | 
5 files changed, 283 insertions, 9 deletions
| @@ -1,16 +1,38 @@  # $Header$ -CC      = g++ -CFLAGS  = -g -O -Wall -Wstrict-prototypes -Wuninitialized -Wno-long-long -Wno-multichar  -DEFINES = -DUNIX +CC       = g++ +CFLAGS   = -g -O -Wall -Wstrict-prototypes -Wuninitialized -Wno-long-long -Wno-multichar +DEFINES  = -DUNIX  LDFLAGS :=  INCLUDES:= `sdl-config --cflags` -I./ -I./sound -CPPFLAGS= $(DEFINES) $(INCLUDES) +LIBS	 = -lncurses + +# Uncomment this to activate the MAD lib for compressed sound files +# DEFINES += -DCOMPRESSED_SOUND_FILE +# LIBS    += -lmad + +# Uncomment this to activate the ALSA lib for midi +# DEFINES += -DUSE_ALSA +# LIBS    += -lasound + -# Add -lmad for -DCOMPRESSED_SOUND_FILE -LIBS	= `sdl-config --libs` -lncurses +# Now, please choose a graphical output system between SDL and X11. +# Beware, only define one of them, otherwise the compilation will blow up. -OBJS	= sdl.o +# Comment this if you want to disable SDL output +OBJS	 = sdl.o +INCLUDE += `sdl-config --cflags` +LIBS    += `sdl-config --libs` + +# Uncomment this if you rather want X11 output +# OBJS     = x11.o +# DEFINES += -DUNIX_X11 +# LDFLAGS := -L/usr/X11R6/lib -L/usr/local/lib +# INCLUDES+= -I/usr/X11R6/include +# LIBS    += -lpthread + + +CPPFLAGS= $(DEFINES) $(INCLUDES)  include Makefile.common diff --git a/gameDetector.cpp b/gameDetector.cpp index 06ed0757f8..f378b511be 100644 --- a/gameDetector.cpp +++ b/gameDetector.cpp @@ -320,6 +320,7 @@ bool GameDetector::parseMusicDriver(const char *s) {  		{"core",MD_COREAUDIO},  		{"amidi",MD_AMIDI},  		{"midiemu",MD_MIDIEMU}, +		{"alsa", MD_ALSA},  		{"adlib",-1},  	}; @@ -608,6 +609,9 @@ MidiDriver *GameDetector::createMidi() {  #if defined(__APPLE__)  	case MD_COREAUDIO:	return MidiDriver_CORE_create();  #endif +#if defined(UNIX) && defined(USE_ALSA) +	case MD_ALSA:		return MidiDriver_ALSA_create(); +#endif  	}  	error("Invalid midi driver selected"); diff --git a/readme.txt b/readme.txt index 3ce3d0685c..514febd4ad 100644 --- a/readme.txt +++ b/readme.txt @@ -320,6 +320,7 @@ depending on your operating system and configuration.          -eqt        - Quicktime sound, for Macintosh users.          -ecore      - CoreAudio sound, for MacOS X users.          -eamidi     - Uses the MorphOS MIDI system, for MorphOS users +	-ealsa      - Output using ALSA sequencer device. See below.          -enull      - Null output. Don't play any music. @@ -330,6 +331,7 @@ as sampled waves. This is the default mode for most games, and offers the  best compatability between machines and games. However, Sam and Max does not  include Adlib emulation. +  Playing sound with MIDI emulation:  ----------------------------------  Until recently, some games (particually Sam and Max) were only able to run @@ -341,12 +343,14 @@ and is the default for Sam and Max on UNIX platforms. -HOWEVER-, it is still  very buggy and the emulation is not perfect. If you are capable of using  native midi, we recommend using one of the MIDI modes below. +  Playing sound with Native MIDI:  -------------------------------  Use the appropriate -e<mode> command line option from the list above to  select your preferred MIDI device. For example, if you wish to use the  Windows MIDI driver, use the -ewindows option. +  Playing sound with Sequencer MIDI:              [UNIX ONLY]  ----------------------------------  If your soundcard driver supports a sequencer, you may set the environment @@ -360,6 +364,48 @@ performance and quality than Adlib or MIDI emulation. However, for those  systems where sequencer support does not work, you can always fall back on  either of those methods. + +Playing sound with ALSA sequencer:              [UNIX ONLY] +---------------------------------- +If you have installed the ALSA driver with the sequencer support, then +set the environment variable "SCUMMVM_PORT" to your sequencer port - eg 65:0 + +Here is a little howto on how to use the ALSA sequencer with your soundcard. +In all cases, to have a list of all the sequencer ports you have, try the +command "aconnect -o -l". On my system it gives me the output: +client 64: 'External MIDI 0' [type=kernel] +    0 'MIDI 0-0        ' +client 65: 'Emu10k1 WaveTable' [type=kernel] +    0 'Emu10k1 Port 0  ' +    1 'Emu10k1 Port 1  ' +    2 'Emu10k1 Port 2  ' +    3 'Emu10k1 Port 3  ' +client 128: 'Client-128' [type=user] +    0 'TiMidity port 0 ' +    1 'TiMidity port 1 ' + +It means the external MIDI output of my sound card is located on the +port 64:0, that I've got four WaveTable MIDI outputs in 65:0, 65:1, 65:2 +and 65:3, and that I've got two TiMidity ports, located at 128:0 and 128:1. + +If you have a FM-chip on your card, like the SB16, then you have to load +the soundfonts using the sbiload software. Example: +  sbiload -p 65:0 /etc/std.o3 /etc/drums.o3 + +If you have a WaveTable capable sound card, you have to load a sbk or sf2 +soundfont using the sfxload software. If you manage to do so, please mail +me since I managed to get it working only once, and never again. + +If you don't have a MIDI capable soundcard, or if you want to take +advantage of your TiMidity samples, then you can ask TiMidity to become an +alsa sequencer output. Here is a quick way to do so: +  timidity -iAqqq -B2,8 -Os1S -s 44100 & + +Then the TiMidity port will be visible from the 'aconnect -o -l' list. You +should launch it beeing as root, since it will try to set up some real time +priority. + +  Using MP3 files for CD audio:  -----------------------------  Use LAME or some other mp3 encoder to rip the cd audio tracks to files. Name @@ -456,7 +502,7 @@ Credits:          Daniel Schepler    - Final MI1 CD music support          Tim 'realmz'       - Initial MI1 CD music support          Jonathan 'khalek'  - Expert weaver in the Loom -        Nicolas Noble      - Config file support +        Nicolas Noble      - Config file and ALSA support          Pawel Kolodziejski - Added missing Dig SMUSH codecs          Felix Jakschitsc   - His hard work on Zak256 diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp index 0dc14f9558..4dfda237e6 100644 --- a/sound/mididrv.cpp +++ b/sound/mididrv.cpp @@ -1444,6 +1444,205 @@ void MidiDriver_MIDIEMU::midi_fm_endnote(int voice) {  } +#if defined(UNIX) && defined(USE_ALSA) + +#include <alsa/asoundlib.h> + +/* + *     ALSA sequencer driver + * Mostly cut'n'pasted from Virtual Tiny Keyboard (vkeybd) by Takashi Iwai + *                                      (you really rox, you know?) + */ + +#if SND_LIB_MINOR >= 6 +#define snd_seq_flush_output(x) snd_seq_drain_output(x) +#define snd_seq_set_client_group(x,name) /*nop*/ +#define my_snd_seq_open(seqp) snd_seq_open(seqp, "hw", SND_SEQ_OPEN_OUTPUT, 0) +#else +/* SND_SEQ_OPEN_OUT causes oops on early version of ALSA */ +#define my_snd_seq_open(seqp) snd_seq_open(seqp, SND_SEQ_OPEN) +#endif + +/* + * parse address string + */ + +#define ADDR_DELIM      ".:" + +static int parse_addr(char *arg, int *client, int *port) +{ +        char *p; + +        if (isdigit(*arg)) { +                if ((p = strpbrk(arg, ADDR_DELIM)) == NULL) +                        return -1; +                *client = atoi(arg); +                *port = atoi(p + 1); +        } else { +                if (*arg == 's' || *arg == 'S') { +                        *client = SND_SEQ_ADDRESS_SUBSCRIBERS; +                        *port = 0; +                } else +                        return -1; +        } +        return 0; +} + +class MidiDriver_ALSA : public MidiDriver { +public: +        MidiDriver_ALSA(); +	int open(int mode); +	void close(); +	void send(uint32 b); +	void pause(bool pause); +	void set_stream_callback(void *param, StreamCallback *sc); + +private: +	void send_event(int do_flush); +        snd_seq_event_t ev; +	StreamCallback *_stream_proc; +	void  *_stream_param; +	int 	 _mode; +	snd_seq_t *seq_handle; +	int seq_client, seq_port; +	int my_client, my_port; +}; + +MidiDriver_ALSA::MidiDriver_ALSA() { +    printf("Driver: ALSA\n"); +} + +void MidiDriver_ALSA::send_event(int do_flush) +{ +        snd_seq_ev_set_direct(&ev); +        snd_seq_ev_set_source(&ev, my_port); +        snd_seq_ev_set_dest(&ev, seq_client, seq_port); + +        snd_seq_event_output(seq_handle, &ev); +        if (do_flush) +                snd_seq_flush_output(seq_handle); +} + +int MidiDriver_ALSA::open(int mode) { +	char * var; +	unsigned int caps; +	 +        if (_mode != 0) +		return MERR_ALREADY_OPEN; +	_mode=mode; +	if (mode!=MO_SIMPLE) return MERR_STREAMING_NOT_AVAILABLE; +	 +	if (!(var = getenv("SCUMMVM_PORT"))) { +		error("You have to define the environnement variable SCUMMVM_PORT"); +		return -1; +	} +	 +	if (parse_addr(var, &seq_client, &seq_port) < 0) { +		error("Invalid port %s", var); +		return -1; +	} + +	if (my_snd_seq_open(&seq_handle)) { +		error("Can't open sequencer"); +		return -1; +	} +	 +	my_client = snd_seq_client_id(seq_handle); +	snd_seq_set_client_name(seq_handle, "SCUMMVM"); +	snd_seq_set_client_group(seq_handle, "input"); +	 +	caps = SND_SEQ_PORT_CAP_READ; +	if (seq_client == SND_SEQ_ADDRESS_SUBSCRIBERS) +		caps = ~SND_SEQ_PORT_CAP_SUBS_READ; +	my_port = snd_seq_create_simple_port(seq_handle, "SCUMMVM", caps, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION); +	if (my_port < 0) { +	    snd_seq_close(seq_handle); +	    error("Can't create port"); +	    return -1; +	} + +        if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) { +                /* subscribe to MIDI port */ +                if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) < 0) { +                        snd_seq_close(seq_handle); +                        error("Can't subscribe to MIDI port (%d:%d)", seq_client, seq_port); +                        return -1; +                } +        } + +	printf("ALSA client initialised [%d:%d]\n", my_client, my_port); +	 +	return 0; +} + +void MidiDriver_ALSA::close() { +    _mode = 0; +    snd_seq_close(seq_handle); +} + + +void MidiDriver_ALSA::send(uint32 b) +{ +	unsigned int midiCmd[4]; +	ev.type = SND_SEQ_EVENT_OSS; +	ev.data.raw8.d[0] = b; + +	midiCmd[3] = (b & 0xFF000000) >> 24; +	midiCmd[2] = (b & 0x00FF0000) >> 16; +	midiCmd[1] = (b & 0x0000FF00) >> 8; +	midiCmd[0] = (b & 0x000000FF); + +	unsigned char chanID = midiCmd[0] & 0x0F; +	switch (midiCmd[0] & 0xF0) { +	case 0x80: +		snd_seq_ev_set_noteoff(&ev, chanID, midiCmd[1], midiCmd[2]); +		send_event(1); +		break; +	case 0x90: +		snd_seq_ev_set_noteon(&ev, chanID, midiCmd[1], midiCmd[2]); +		send_event(1); +		break; + +	case 0xB0:										// Effect +		snd_seq_ev_set_controller(&ev, chanID, midiCmd[1], midiCmd[2]); +		send_event(1); +		break; +	case 0xC0: +		snd_seq_ev_set_pgmchange(&ev, chanID, midiCmd[1]); +		send_event(0); +		break; + +	case 0xE0:{									// Pitch bend +			long theBend = +				((((long)midiCmd[1] + (long)(midiCmd[2] << 8))) - 0x4000) / 4; +			snd_seq_ev_set_pitchbend(&ev, chanID, theBend); +			send_event(1); +		} +		break; + +	default: +		error("Unknown Command: %08x\n", (int)b); +		break; +	} +} + +void MidiDriver_ALSA::pause(bool pause) { +	if (_mode == MO_STREAMING) { +	} +} + +void MidiDriver_ALSA::set_stream_callback(void *param, StreamCallback *sc) { +	_stream_param = param; +	_stream_proc = sc; +} + +MidiDriver *MidiDriver_ALSA_create() { +	return new MidiDriver_ALSA(); +} + +#endif + +  #if 0  /* Old code for timidity support, maybe somebody can rewrite this for the  @@ -1503,3 +1702,4 @@ void MidiDriver::midiInitTimidity()  #endif /* 0 */ + diff --git a/sound/mididrv.h b/sound/mididrv.h index a24ee458ce..977308afe8 100644 --- a/sound/mididrv.h +++ b/sound/mididrv.h @@ -106,7 +106,8 @@ enum {  	MD_QTMUSIC = 5,  	MD_AMIDI = 6,  	MD_COREAUDIO = 7, -	MD_MIDIEMU = 8 +	MD_MIDIEMU = 8, +	MD_ALSA = 9,  }; @@ -120,3 +121,4 @@ extern MidiDriver *MidiDriver_QT_create();  extern MidiDriver *MidiDriver_CORE_create();  extern MidiDriver *MidiDriver_AMIDI_create();  extern MidiDriver *MidiDriver_MIDIEMU_create(); +extern MidiDriver *MidiDriver_ALSA_create(); | 
