diff options
author | Jamieson Christian | 2002-12-11 02:08:32 +0000 |
---|---|---|
committer | Jamieson Christian | 2002-12-11 02:08:32 +0000 |
commit | 7d3a423df7064a212960cd9e75d9c722a883e776 (patch) | |
tree | 44b92675ba6ccc296542c567570c45d4037a4345 | |
parent | 14834cf645e6b1c18e4c03d5e4af847955c91a75 (diff) | |
download | scummvm-rg350-7d3a423df7064a212960cd9e75d9c722a883e776.tar.gz scummvm-rg350-7d3a423df7064a212960cd9e75d9c722a883e776.tar.bz2 scummvm-rg350-7d3a423df7064a212960cd9e75d9c722a883e776.zip |
Separated Windows MIDI driver into its own file
svn-id: r5901
-rw-r--r-- | backends/midi/windows.cpp | 278 | ||||
-rw-r--r-- | sound/mididrv.cpp | 251 |
2 files changed, 278 insertions, 251 deletions
diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp new file mode 100644 index 0000000000..6d7322a928 --- /dev/null +++ b/backends/midi/windows.cpp @@ -0,0 +1,278 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001 Ludvig Strigeus + * Copyright (C) 2001/2002 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + */ + +#if defined(WIN32) && !defined(_WIN32_WCE) + +#include "stdafx.h" +#include "sound/mpu401.h" +#include "common/engine.h" // For warning/error/debug + +//////////////////////////////////////// +// +// Windows MIDI driver +// +//////////////////////////////////////// + +class MidiDriver_WIN : public MidiDriver_MPU401 { +public: + int open(int mode); + void close(); + void send(uint32 b); + void pause(bool p); + void set_stream_callback(void *param, StreamCallback *sc); + +private: + struct MyMidiHdr { + MIDIHDR hdr; + }; + + enum { + NUM_PREPARED_HEADERS = 2, + MIDI_EVENT_SIZE = 64, + BUFFER_SIZE = MIDI_EVENT_SIZE * 12, + }; + + StreamCallback *_stream_proc; + void *_stream_param; + int _mode; + + HMIDIOUT _mo; + HMIDISTRM _ms; + + MyMidiHdr *_prepared_headers; + + uint16 _time_div; + + void unprepare(); + void prepare(); + void check_error(MMRESULT result); + void fill_all(); + uint32 property(int prop, uint32 param); + + static void CALLBACK midi_callback(HMIDIOUT hmo, UINT wMsg, + DWORD dwInstance, DWORD dwParam1, DWORD dwParam2); +}; + +void MidiDriver_WIN::set_stream_callback(void *param, StreamCallback *sc) +{ + _stream_param = param; + _stream_proc = sc; +} + +void CALLBACK MidiDriver_WIN::midi_callback(HMIDIOUT hmo, UINT wMsg, + DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) +{ + + switch (wMsg) { + case MM_MOM_DONE:{ + MidiDriver_WIN *md = ((MidiDriver_WIN *) dwInstance); + if (md->_mode) + md->fill_all(); + break; + } + } +} + +int MidiDriver_WIN::open(int mode) +{ + if (_mode != 0) + return MERR_ALREADY_OPEN; + + _mode = mode; + + if (mode == MO_SIMPLE) { + MMRESULT res = midiOutOpen((HMIDIOUT *) & _mo, MIDI_MAPPER, 0, 0, 0); + if (res != MMSYSERR_NOERROR) + check_error(res); + } else { + // Streaming mode + MIDIPROPTIMEDIV mptd; + UINT _midi_device_id = 0; + + check_error(midiStreamOpen(&_ms, &_midi_device_id, 1, + (uint32)midi_callback, (uint32)this, CALLBACK_FUNCTION)); + + prepare(); + + mptd.cbStruct = sizeof(mptd); + mptd.dwTimeDiv = _time_div; + + check_error(midiStreamProperty(_ms, (byte *)&mptd, MIDIPROP_SET | MIDIPROP_TIMEDIV)); + + fill_all(); + } + + return 0; +} + +void MidiDriver_WIN::fill_all() +{ + if (_stream_proc == NULL) { + error("MidiDriver_WIN::fill_all() called, but _stream_proc==NULL"); + } + + uint i; + MyMidiHdr *mmh = _prepared_headers; + MidiEvent my_evs[64]; + + for (i = 0; i != NUM_PREPARED_HEADERS; i++, mmh++) { + if (!(mmh->hdr.dwFlags & MHDR_INQUEUE)) { + int num = _stream_proc(_stream_param, my_evs, 64); + int i; + + // End of stream? + if (num == 0) + break; + + MIDIEVENT *ev = (MIDIEVENT *)mmh->hdr.lpData; + MidiEvent *my_ev = my_evs; + + for (i = 0; i != num; i++, my_ev++) { + ev->dwStreamID = 0; + ev->dwDeltaTime = my_ev->delta; + + switch (my_ev->event >> 24) { + case 0: + ev->dwEvent = my_ev->event; + break; + case ME_TEMPO: + // Change tempo event + ev->dwEvent = (ME_TEMPO << 24) | (my_ev->event & 0xFFFFFF); + break; + default: + error("Invalid event type passed"); + } + + // Increase stream pointer by 12 bytes. + // (Need to be 12 bytes, and sizeof(MIDIEVENT) is 16) + ev = (MIDIEVENT *)((byte *)ev + 12); + } + + mmh->hdr.dwBytesRecorded = num * 12; + check_error(midiStreamOut(_ms, &mmh->hdr, sizeof(mmh->hdr))); + } + } +} + +void MidiDriver_WIN::prepare() +{ + int i; + MyMidiHdr *mmh; + + _prepared_headers = (MyMidiHdr *) calloc(sizeof(MyMidiHdr), 2); + + for (i = 0, mmh = _prepared_headers; i != NUM_PREPARED_HEADERS; i++, mmh++) { + mmh->hdr.dwBufferLength = BUFFER_SIZE; + mmh->hdr.lpData = (LPSTR) calloc(BUFFER_SIZE, 1); + + check_error(midiOutPrepareHeader((HMIDIOUT) _ms, &mmh->hdr, sizeof(mmh->hdr))); + } +} + +void MidiDriver_WIN::unprepare() +{ + uint i; + MyMidiHdr *mmh = _prepared_headers; + + for (i = 0; i != NUM_PREPARED_HEADERS; i++, mmh++) { + check_error(midiOutUnprepareHeader((HMIDIOUT) _ms, &mmh->hdr, sizeof(mmh->hdr))); + free(mmh->hdr.lpData); + mmh->hdr.lpData = NULL; + } + + free(_prepared_headers); +} + +void MidiDriver_WIN::close() +{ + int mode_was = _mode; + _mode = 0; + + switch (mode_was) { + case MO_SIMPLE: + check_error(midiOutClose(_mo)); + break; + case MO_STREAMING:; + check_error(midiStreamStop(_ms)); + check_error(midiOutReset((HMIDIOUT) _ms)); + unprepare(); + check_error(midiStreamClose(_ms)); + break; + } +} + +void MidiDriver_WIN::send(uint32 b) +{ + union { + DWORD dwData; + BYTE bData[4]; + } u; + + if (_mode != MO_SIMPLE) + error("MidiDriver_WIN:send called but driver is not in simple mode"); + + u.bData[3] = (byte)((b & 0xFF000000) >> 24); + u.bData[2] = (byte)((b & 0x00FF0000) >> 16); + u.bData[1] = (byte)((b & 0x0000FF00) >> 8); + u.bData[0] = (byte)(b & 0x000000FF); + + // printMidi(u.bData[0], u.bData[1], u.bData[2], u.bData[3]); + check_error(midiOutShortMsg(_mo, u.dwData)); +} + +void MidiDriver_WIN::pause(bool p) +{ + if (_mode == MO_STREAMING) { + if (p) + check_error(midiStreamPause(_ms)); + else + check_error(midiStreamRestart(_ms)); + } +} + +void MidiDriver_WIN::check_error(MMRESULT result) +{ + char buf[200]; + if (result != MMSYSERR_NOERROR) { + midiOutGetErrorText(result, buf, 200); + warning("MM System Error '%s'", buf); + } +} + +uint32 MidiDriver_WIN::property(int prop, uint32 param) +{ + switch (prop) { + + // 16-bit time division per the standard MIDI specification + case PROP_TIMEDIV: + _time_div = (uint16)param; + return 1; + } + + return 0; +} + +MidiDriver *MidiDriver_WIN_create() +{ + return new MidiDriver_WIN(); +} + +#endif diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp index 9e1ca82db8..d473ed128b 100644 --- a/sound/mididrv.cpp +++ b/sound/mididrv.cpp @@ -57,257 +57,6 @@ const char *MidiDriver::get_error_name(int error_code) return midi_errors[error_code]; } -#if defined(WIN32) && !defined(_WIN32_WCE) - -/* Windows MIDI driver */ -class MidiDriver_WIN : public MidiDriver_MPU401 { -public: - int open(int mode); - void close(); - void send(uint32 b); - void pause(bool p); - void set_stream_callback(void *param, StreamCallback *sc); - // void setPitchBendRange (byte channel, uint range); - -private: - struct MyMidiHdr { - MIDIHDR hdr; - }; - - enum { - NUM_PREPARED_HEADERS = 2, - MIDI_EVENT_SIZE = 64, - BUFFER_SIZE = MIDI_EVENT_SIZE * 12, - }; - - StreamCallback *_stream_proc; - void *_stream_param; - int _mode; - - HMIDIOUT _mo; - HMIDISTRM _ms; - - MyMidiHdr *_prepared_headers; - - uint16 _time_div; - - void unprepare(); - void prepare(); - void check_error(MMRESULT result); - void fill_all(); - uint32 property(int prop, uint32 param); - - static void CALLBACK midi_callback(HMIDIOUT hmo, UINT wMsg, - DWORD dwInstance, DWORD dwParam1, DWORD dwParam2); -}; - -void MidiDriver_WIN::set_stream_callback(void *param, StreamCallback *sc) -{ - _stream_param = param; - _stream_proc = sc; -} - -void CALLBACK MidiDriver_WIN::midi_callback(HMIDIOUT hmo, UINT wMsg, - DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) -{ - - switch (wMsg) { - case MM_MOM_DONE:{ - MidiDriver_WIN *md = ((MidiDriver_WIN *) dwInstance); - if (md->_mode) - md->fill_all(); - break; - } - } -} - -int MidiDriver_WIN::open(int mode) -{ - if (_mode != 0) - return MERR_ALREADY_OPEN; - - _mode = mode; - - if (mode == MO_SIMPLE) { - MMRESULT res = midiOutOpen((HMIDIOUT *) & _mo, MIDI_MAPPER, 0, 0, 0); - if (res != MMSYSERR_NOERROR) - check_error(res); - } else { - /* streaming mode */ - MIDIPROPTIMEDIV mptd; - UINT _midi_device_id = 0; - - check_error(midiStreamOpen(&_ms, &_midi_device_id, 1, - (uint32)midi_callback, (uint32)this, CALLBACK_FUNCTION)); - - prepare(); - - mptd.cbStruct = sizeof(mptd); - mptd.dwTimeDiv = _time_div; - - check_error(midiStreamProperty(_ms, (byte *)&mptd, MIDIPROP_SET | MIDIPROP_TIMEDIV)); - - fill_all(); - } - - return 0; -} - -void MidiDriver_WIN::fill_all() -{ - if (_stream_proc == NULL) { - error("MidiDriver_WIN::fill_all() called, but _stream_proc==NULL"); - } - - uint i; - MyMidiHdr *mmh = _prepared_headers; - MidiEvent my_evs[64]; - - for (i = 0; i != NUM_PREPARED_HEADERS; i++, mmh++) { - if (!(mmh->hdr.dwFlags & MHDR_INQUEUE)) { - int num = _stream_proc(_stream_param, my_evs, 64); - int i; - - /* end of stream? */ - if (num == 0) - break; - - MIDIEVENT *ev = (MIDIEVENT *)mmh->hdr.lpData; - MidiEvent *my_ev = my_evs; - - for (i = 0; i != num; i++, my_ev++) { - ev->dwStreamID = 0; - ev->dwDeltaTime = my_ev->delta; - - switch (my_ev->event >> 24) { - case 0: - ev->dwEvent = my_ev->event; - break; - case ME_TEMPO: - /* change tempo event */ - ev->dwEvent = (ME_TEMPO << 24) | (my_ev->event & 0xFFFFFF); - break; - default: - error("Invalid event type passed"); - } - - /* increase stream pointer by 12 bytes - * (need to be 12 bytes, and sizeof(MIDIEVENT) is 16) - */ - ev = (MIDIEVENT *)((byte *)ev + 12); - } - - mmh->hdr.dwBytesRecorded = num * 12; - check_error(midiStreamOut(_ms, &mmh->hdr, sizeof(mmh->hdr))); - } - } -} - -void MidiDriver_WIN::prepare() -{ - int i; - MyMidiHdr *mmh; - - _prepared_headers = (MyMidiHdr *) calloc(sizeof(MyMidiHdr), 2); - - for (i = 0, mmh = _prepared_headers; i != NUM_PREPARED_HEADERS; i++, mmh++) { - mmh->hdr.dwBufferLength = BUFFER_SIZE; - mmh->hdr.lpData = (LPSTR) calloc(BUFFER_SIZE, 1); - - check_error(midiOutPrepareHeader((HMIDIOUT) _ms, &mmh->hdr, sizeof(mmh->hdr))); - } -} - -void MidiDriver_WIN::unprepare() -{ - uint i; - MyMidiHdr *mmh = _prepared_headers; - - for (i = 0; i != NUM_PREPARED_HEADERS; i++, mmh++) { - check_error(midiOutUnprepareHeader((HMIDIOUT) _ms, &mmh->hdr, sizeof(mmh->hdr))); - free(mmh->hdr.lpData); - mmh->hdr.lpData = NULL; - } - - free(_prepared_headers); -} - -void MidiDriver_WIN::close() -{ - int mode_was = _mode; - _mode = 0; - - switch (mode_was) { - case MO_SIMPLE: - check_error(midiOutClose(_mo)); - break; - case MO_STREAMING:; - check_error(midiStreamStop(_ms)); - check_error(midiOutReset((HMIDIOUT) _ms)); - unprepare(); - check_error(midiStreamClose(_ms)); - break; - } -} - -void MidiDriver_WIN::send(uint32 b) -{ - union { - DWORD dwData; - BYTE bData[4]; - } u; - - if (_mode != MO_SIMPLE) - error("MidiDriver_WIN:send called but driver is not in simple mode"); - - u.bData[3] = (byte)((b & 0xFF000000) >> 24); - u.bData[2] = (byte)((b & 0x00FF0000) >> 16); - u.bData[1] = (byte)((b & 0x0000FF00) >> 8); - u.bData[0] = (byte)(b & 0x000000FF); - - //printMidi(u.bData[0], u.bData[1], u.bData[2], u.bData[3]); - check_error(midiOutShortMsg(_mo, u.dwData)); -} - -void MidiDriver_WIN::pause(bool p) -{ - if (_mode == MO_STREAMING) { - if (p) - check_error(midiStreamPause(_ms)); - else - check_error(midiStreamRestart(_ms)); - } -} - -void MidiDriver_WIN::check_error(MMRESULT result) -{ - char buf[200]; - if (result != MMSYSERR_NOERROR) { - midiOutGetErrorText(result, buf, 200); - warning("MM System Error '%s'", buf); - } -} - -uint32 MidiDriver_WIN::property(int prop, uint32 param) -{ - switch (prop) { - - /* 16-bit time division according to standard midi specification */ - case PROP_TIMEDIV: - _time_div = (uint16)param; - return 1; - } - - return 0; -} - -MidiDriver *MidiDriver_WIN_create() -{ - return new MidiDriver_WIN(); -} - -#endif // WIN32 - #ifdef __MORPHOS__ #include <exec/memory.h> #include <exec/types.h> |