Bochs/bochs/iodev/sound/soundwin.h
Volker Ruppert bdd8875692 Reverted BX_THREAD_KILL() changes in the lowlevel sound code. Now using control
variables again to let the threads end normally. Re-implenented the method
closewaveoutput() for some modules, move the destructor code to it and call it
after leaving the mixer thread. This fixes a deadlock in the "soundwin" module
if Bochs is compiled with plugin support.
2017-06-02 16:56:58 +00:00

237 lines
6.3 KiB
C++

/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2015 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
/////////////////////////////////////////////////////////////////////////
// This file (SOUNDWIN.H) written and donated by Josef Drexler
#if BX_HAVE_SOUND_WIN
#include <mmsystem.h>
#define BX_SOUND_WINDOWS_MAXSYSEXLEN 256 // maximum supported length of a sysex message
#ifndef WAVEMAPPER
#define WAVEMAPPER -1
#endif
// Definitions for WINMM.DLL, if not defined already
#ifndef MMSYSERR_NOERROR
#pragma pack(1)
typedef UINT HMIDIOUT;
typedef HMIDIOUT *LPHMIDIOUT;
typedef struct midihdr_tag {
LPSTR lpData;
DWORD dwBufferLength;
DWORD dwBytesRecorded;
DWORD dwUser;
DWORD dwFlags;
struct midihdr_tag *lpNext;
DWORD reserved;
} MIDIHDR, *LPMIDIHDR;
typedef UINT HWAVEOUT;
typedef HWAVEOUT *LPHWAVEOUT;
typedef struct wavehdr_tag {
LPSTR lpData;
DWORD dwBufferLength;
DWORD dwBytesRecorded;
DWORD dwUser;
DWORD dwFlags;
DWORD dwLoops;
struct wavehdr_tag *lpNext;
DWORD reserved;
} WAVEHDR, *LPWAVEHDR;
#define WHDR_DONE 0x00000001
#define WHDR_PREPARED 0x00000002
#define WHDR_BEGINLOOP 0x00000004
#define WHDR_ENDLOOP 0x00000008
#define WHDR_INQUEUE 0x00000010
typedef struct waveformat_tag {
WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
} WAVEFORMAT, *LPWAVEFORMAT;
#define WAVE_FORMAT_PCM 1
typedef struct pcmwaveformat_tag {
WAVEFORMAT wf;
WORD wBitsPerSample;
} PCMWAVEFORMAT, *LPPCMWAVEFORMAT;
#define MIDIMAPPER -1
#define CALLBACK_NULL 0x00000000
#define CALLBACK_WINDOW 0x00010000
#define CALLBACK_TASK 0x00020000
#define CALLBACK_FUNCTION 0x00030000
#define MMSYSERR_NOERROR 0
#define MMSYSERR_ERROR 1
#define MMSYSERR_BADDEVICEID 2
#define MMSYSERR_NOTENABLED 3
#define MMSYSERR_ALLOCATED 4
#define MMSYSERR_INVALHANDLE 5
#define MMSYSERR_NODRIVER 6
#define MMSYSERR_NOMEM 7
#define MMSYSERR_NOTSUPPORTED 8
#define MMSYSERR_NOMAP 7
#define MIDIERR_UNPREPARED 64
#define MIDIERR_STILLPLAYING 65
#define MIDIERR_NOTREADY 66
#define MIDIERR_NODEVICE 67
#define WAVERR_BADFORMAT 32
#define WAVERR_STILLPLAYING 33
#define WAVERR_UNPREPARED 34
#define WAVERR_SYNC 35
#define MAXERRORLENGTH 128
extern "C" {
UINT STDCALL midiOutOpen(LPHMIDIOUT, UINT, DWORD, DWORD, DWORD);
UINT STDCALL midiOutShortMsg(HMIDIOUT, DWORD);
UINT STDCALL midiOutLongMsg(HMIDIOUT, LPMIDIHDR, UINT);
UINT STDCALL midiOutPrepareHeader(HMIDIOUT, LPMIDIHDR, UINT);
UINT STDCALL midiOutUnprepareHeader(HMIDIOUT, LPMIDIHDR, UINT);
UINT STDCALL midiOutReset(HMIDIOUT);
UINT STDCALL midiOutClose(HMIDIOUT);
UINT STDCALL waveOutOpen(LPHWAVEOUT, UINT, LPWAVEFORMAT, DWORD, DWORD, DWORD);
UINT STDCALL waveOutWrite(HWAVEOUT, LPWAVEHDR, UINT);
UINT STDCALL waveOutPrepareHeader(HWAVEOUT, LPWAVEHDR, UINT);
UINT STDCALL waveOutUnprepareHeader(HWAVEOUT, LPWAVEHDR, UINT);
UINT STDCALL waveOutReset(HWAVEOUT);
UINT STDCALL waveOutClose(HWAVEOUT);
UINT STDCALL waveOutGetErrorTextA(UINT, LPSTR, UINT);
BOOL STDCALL sndPlaySoundA(LPCSTR, UINT);
}
#pragma pack(0)
#endif // MMSYSERR_NOERROR defined
#ifndef WAVEFILEHEADER
#pragma pack(push, 1)
typedef struct {
char RIFF[4];
Bit32u length;
char TYPE[4];
char chnk[4];
Bit32u chnklen;
PCMWAVEFORMAT waveformat;
char chnk2[4];
Bit32u chnk2len;
char data[1];
} WAVEFILEHEADER, *LPWAVEFILEHEADER;
#pragma pack(pop)
#endif
class bx_soundlow_waveout_win_c : public bx_soundlow_waveout_c {
public:
bx_soundlow_waveout_win_c();
virtual ~bx_soundlow_waveout_win_c() {}
virtual int openwaveoutput(const char *wavedev);
virtual int set_pcm_params(bx_pcm_param_t *param);
virtual int get_packetsize();
virtual int output(int length, Bit8u data[]);
virtual int closewaveoutput();
private:
HWAVEOUT hWaveOut; // Wave output device
int WaveOutOpen; // is it open?
UINT WaveDevice; // Wave device ID, for waveOutOpen
LPWAVEHDR WaveOutHdr;
};
class bx_soundlow_wavein_win_c : public bx_soundlow_wavein_c {
public:
bx_soundlow_wavein_win_c();
virtual ~bx_soundlow_wavein_win_c();
virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh);
virtual int startwaverecord(bx_pcm_param_t *param);
virtual int getwavepacket(int length, Bit8u data[]);
virtual int stopwaverecord();
static void record_timer_handler(void *);
void record_timer(void);
private:
bx_pcm_param_t wavein_param;
HWAVEIN hWaveIn; // Wave input device
int WaveInOpen; // is it open?
LPWAVEHDR WaveInHdr;
LPSTR WaveInData;
bx_bool recording;
int recordnextpacket();
};
class bx_soundlow_midiout_win_c : public bx_soundlow_midiout_c {
public:
bx_soundlow_midiout_win_c();
virtual ~bx_soundlow_midiout_win_c();
virtual int openmidioutput(const char *mididev);
virtual int midiready();
virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
virtual int closemidioutput();
private:
HMIDIOUT MidiOut; // Midi output device
int MidiOpen; // is it open?
// and the midi buffer for the SYSEX messages
LPMIDIHDR MidiHeader;
LPSTR MidiData;
int ismidiready;
void checkmidiready();
};
class bx_sound_windows_c : public bx_sound_lowlevel_c {
public:
bx_sound_windows_c();
virtual ~bx_sound_windows_c();
virtual bx_soundlow_waveout_c* get_waveout();
virtual bx_soundlow_wavein_c* get_wavein();
virtual bx_soundlow_midiout_c* get_midiout();
} bx_sound_windows;
#endif // BX_HAVE_SOUND_WIN