1 /////////////////////////////////////////////////////////////////////////
2 // $Id: soundwin.h 14116 2021-01-31 15:44:39Z vruppert $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //  Copyright (C) 2001-2021  The Bochs Project
6 //
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Lesser General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Lesser General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Lesser General Public
18 //  License along with this library; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20 /////////////////////////////////////////////////////////////////////////
21 
22 // This file (SOUNDWIN.H) written and donated by Josef Drexler
23 
24 #if BX_HAVE_SOUND_WIN
25 
26 #include <mmsystem.h>
27 
28 #define BX_SOUND_WINDOWS_MAXSYSEXLEN  256    // maximum supported length of a sysex message
29 
30 #ifndef WAVEMAPPER
31 #define WAVEMAPPER -1
32 #endif
33 
34 // Definitions for WINMM.DLL, if not defined already
35 #ifndef MMSYSERR_NOERROR
36 
37 #pragma pack(1)
38 
39 typedef UINT HMIDIOUT;
40 typedef	HMIDIOUT *LPHMIDIOUT;
41 typedef struct midihdr_tag {
42     LPSTR lpData;
43     DWORD dwBufferLength;
44     DWORD dwBytesRecorded;
45     DWORD dwUser;
46     DWORD dwFlags;
47     struct midihdr_tag *lpNext;
48     DWORD reserved;
49 } MIDIHDR, *LPMIDIHDR;
50 
51 typedef UINT HWAVEOUT;
52 typedef HWAVEOUT *LPHWAVEOUT;
53 
54 typedef struct wavehdr_tag {
55     LPSTR lpData;
56     DWORD dwBufferLength;
57     DWORD dwBytesRecorded;
58     DWORD dwUser;
59     DWORD dwFlags;
60     DWORD dwLoops;
61     struct wavehdr_tag *lpNext;
62     DWORD reserved;
63 } WAVEHDR, *LPWAVEHDR;
64 
65 #define WHDR_DONE         0x00000001
66 #define WHDR_PREPARED     0x00000002
67 #define WHDR_BEGINLOOP    0x00000004
68 #define WHDR_ENDLOOP      0x00000008
69 #define WHDR_INQUEUE      0x00000010
70 
71 
72 typedef struct waveformat_tag {
73     WORD wFormatTag;
74     WORD nChannels;
75     DWORD nSamplesPerSec;
76     DWORD nAvgBytesPerSec;
77     WORD nBlockAlign;
78 } WAVEFORMAT, *LPWAVEFORMAT;
79 
80 #define WAVE_FORMAT_PCM 	1
81 
82 typedef struct pcmwaveformat_tag {
83     WAVEFORMAT wf;
84     WORD wBitsPerSample;
85 } PCMWAVEFORMAT, *LPPCMWAVEFORMAT;
86 
87 #define MIDIMAPPER		-1
88 
89 #define CALLBACK_NULL		0x00000000
90 #define CALLBACK_WINDOW		0x00010000
91 #define CALLBACK_TASK		0x00020000
92 #define CALLBACK_FUNCTION	0x00030000
93 
94 #define MMSYSERR_NOERROR	0
95 #define MMSYSERR_ERROR		1
96 #define MMSYSERR_BADDEVICEID	2
97 #define MMSYSERR_NOTENABLED	3
98 #define MMSYSERR_ALLOCATED      4
99 #define MMSYSERR_INVALHANDLE	5
100 #define MMSYSERR_NODRIVER	6
101 #define MMSYSERR_NOMEM		7
102 #define MMSYSERR_NOTSUPPORTED	8
103 #define MMSYSERR_NOMAP		7
104 
105 #define MIDIERR_UNPREPARED      64
106 #define MIDIERR_STILLPLAYING    65
107 #define MIDIERR_NOTREADY	66
108 #define MIDIERR_NODEVICE        67
109 
110 #define WAVERR_BADFORMAT        32
111 #define WAVERR_STILLPLAYING     33
112 #define WAVERR_UNPREPARED       34
113 #define WAVERR_SYNC             35
114 
115 #define MAXERRORLENGTH		128
116 
117 extern "C" {
118 UINT STDCALL midiOutOpen(LPHMIDIOUT, UINT, DWORD, DWORD, DWORD);
119 UINT STDCALL midiOutShortMsg(HMIDIOUT, DWORD);
120 UINT STDCALL midiOutLongMsg(HMIDIOUT, LPMIDIHDR, UINT);
121 UINT STDCALL midiOutPrepareHeader(HMIDIOUT, LPMIDIHDR, UINT);
122 UINT STDCALL midiOutUnprepareHeader(HMIDIOUT, LPMIDIHDR, UINT);
123 UINT STDCALL midiOutReset(HMIDIOUT);
124 UINT STDCALL midiOutClose(HMIDIOUT);
125 
126 UINT STDCALL waveOutOpen(LPHWAVEOUT, UINT, LPWAVEFORMAT, DWORD, DWORD, DWORD);
127 UINT STDCALL waveOutWrite(HWAVEOUT, LPWAVEHDR, UINT);
128 UINT STDCALL waveOutPrepareHeader(HWAVEOUT, LPWAVEHDR, UINT);
129 UINT STDCALL waveOutUnprepareHeader(HWAVEOUT, LPWAVEHDR, UINT);
130 UINT STDCALL waveOutReset(HWAVEOUT);
131 UINT STDCALL waveOutClose(HWAVEOUT);
132 
133 UINT STDCALL waveOutGetErrorTextA(UINT, LPSTR, UINT);
134 
135 BOOL STDCALL sndPlaySoundA(LPCSTR, UINT);
136 }
137 #pragma pack(0)
138 
139 #endif  // MMSYSERR_NOERROR defined
140 
141 #ifndef WAVEFILEHEADER
142 
143 #pragma pack(push, 1)
144 
145 typedef struct {
146   char RIFF[4];
147   Bit32u length;
148   char TYPE[4];
149   char chnk[4];
150   Bit32u chnklen;
151   PCMWAVEFORMAT waveformat;
152   char chnk2[4];
153   Bit32u chnk2len;
154   char data[1];
155 } WAVEFILEHEADER, *LPWAVEFILEHEADER;
156 #pragma pack(pop)
157 
158 #endif
159 
160 class bx_soundlow_waveout_win_c : public bx_soundlow_waveout_c {
161 public:
162   bx_soundlow_waveout_win_c();
~bx_soundlow_waveout_win_c()163   virtual ~bx_soundlow_waveout_win_c() {}
164 
165   virtual int openwaveoutput(const char *wavedev);
166   virtual int set_pcm_params(bx_pcm_param_t *param);
167   virtual int get_packetsize();
168   virtual int output(int length, Bit8u data[]);
169   virtual int closewaveoutput();
170 private:
171   HWAVEOUT hWaveOut;      // Wave output device
172   int WaveOutOpen;        // is it open?
173 
174   UINT WaveDevice;        // Wave device ID, for waveOutOpen
175 
176   LPWAVEHDR WaveOutHdr;
177 };
178 
179 class bx_soundlow_wavein_win_c : public bx_soundlow_wavein_c {
180 public:
181   bx_soundlow_wavein_win_c();
182   virtual ~bx_soundlow_wavein_win_c();
183 
184   virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh);
185   virtual int startwaverecord(bx_pcm_param_t *param);
186   virtual int getwavepacket(int length, Bit8u data[]);
187   virtual int stopwaverecord();
188 
189   static void record_timer_handler(void *);
190   void record_timer(void);
191 private:
192   bx_pcm_param_t wavein_param;
193 
194   HWAVEIN hWaveIn;        // Wave input device
195   int WaveInOpen;         // is it open?
196 
197   LPWAVEHDR WaveInHdr;
198   LPSTR WaveInData;
199   bool recording;
200 
201   int recordnextpacket();
202 };
203 
204 class bx_soundlow_midiout_win_c : public bx_soundlow_midiout_c {
205 public:
206   bx_soundlow_midiout_win_c();
207   virtual ~bx_soundlow_midiout_win_c();
208 
209   virtual int openmidioutput(const char *mididev);
210   virtual int midiready();
211   virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]);
212   virtual int closemidioutput();
213 
214 private:
215   HMIDIOUT MidiOut;       // Midi output device
216   int MidiOpen;           // is it open?
217 
218   // and the midi buffer for the SYSEX messages
219   LPMIDIHDR MidiHeader;
220   LPSTR MidiData;
221   int ismidiready;
222 
223   void checkmidiready();
224 };
225 
226 class bx_sound_windows_c : public bx_sound_lowlevel_c {
227 public:
228   bx_sound_windows_c();
229   virtual ~bx_sound_windows_c();
230 
231   virtual bx_soundlow_waveout_c* get_waveout();
232   virtual bx_soundlow_wavein_c* get_wavein();
233   virtual bx_soundlow_midiout_c* get_midiout();
234 } bx_sound_windows;
235 
236 #endif  // BX_HAVE_SOUND_WIN
237