]>
git.saurik.com Git - wxWidgets.git/blob - utils/wxMMedia/sndwin.cpp
1 ////////////////////////////////////////////////////////////////////////////////
4 // Author: Guilhem Lavaux
7 // Copyright: (C) 1997, 1998, Guilhem Lavaux
8 // License: wxWindows license
9 ////////////////////////////////////////////////////////////////////////////////
11 #include "wx/wxprec.h"
15 #include <wx/msw/private.h>
17 #define WXMMEDIA_INTERNAL
20 #define MMD_WIN_IO_BSIZE 16384
28 wxSndWinFragment::wxSndWinFragment(wxSound
& io_drv
)
29 : wxFragmentBuffer(io_drv
)
33 wxSndWinFragment::~wxSndWinFragment(void)
37 void wxSndWinFragment::AllocIOBuffer(void)
39 wxWinSound
*w_snd
= (wxWinSound
*) m_iodrv
;
45 m_lstoptrs
= new wxFragBufPtr
[m_maxoq
];
46 m_lstiptrs
= new wxFragBufPtr
[m_maxiq
];
48 for (i
=0;i
<m_maxoq
;i
++) {
49 m_lstoptrs
[i
].buffers
= new wxList();
50 m_lstoptrs
[i
].state
= wxBUFFER_FREE
;
52 w_snd
->PrepareHeader(m_lstoptrs
[i
], wxSND_OUTPUT
);
55 for (i
=0;i
<m_maxiq
;i
++) {
56 m_lstiptrs
[i
].size
= MMD_WIN_IO_BSIZE
;
57 m_lstiptrs
[i
].ptr
= 0;
58 m_lstiptrs
[i
].buffers
= new wxList();
59 m_lstiptrs
[i
].state
= wxBUFFER_FREE
;
61 w_snd
->PrepareHeader(m_lstiptrs
[i
], wxSND_INPUT
);
65 void wxSndWinFragment::FreeIOBuffer(void)
67 wxWinSound
*w_snd
= (wxWinSound
*)m_iodrv
;
70 if (!m_lstoptrs
&& !m_lstiptrs
)
73 for (i
=0;i
<m_maxoq
;i
++) {
74 w_snd
->UnprepareHeader(m_lstoptrs
[i
], wxSND_OUTPUT
);
75 delete m_lstoptrs
[i
].buffers
;
78 for (i
=0;i
<m_maxiq
;i
++) {
79 w_snd
->UnprepareHeader(m_lstiptrs
[i
], wxSND_INPUT
);
80 delete m_lstiptrs
[i
].buffers
;
86 m_lstoptrs
= m_lstiptrs
= NULL
;
87 m_maxoq
= m_maxiq
= 0;
90 void wxSndWinFragment::WaitForAll()
100 for (i
=0;i
<m_maxoq
;i
++) {
101 if (m_lstoptrs
[i
].state
== wxBUFFER_FFILLED
) {
113 bool wxSndWinFragment::OnBufferFilled(wxFragBufPtr
*ptr
, wxSndMode mode
)
115 wxSndWinInfo
*info
= (wxSndWinInfo
*)ptr
->user_data
;
116 wxWinSound
*w_snd
= (wxWinSound
*)m_iodrv
;
121 result
= waveInAddBuffer(w_snd
->internal
->devin_id
, info
->hdr
,
125 result
= waveOutWrite(w_snd
->internal
->devout_id
, info
->hdr
,
127 printf("WINOUT: result=%d\n", result
);
133 wxWinSound::wxWinSound(void)
137 internal
= new wxWinSoundInternal
;
138 internal
->devout_id
= 0;
139 internal
->devin_id
= 0;
140 internal
->sndWin
= 0;
144 curr_o_srate
= (wxUint32
)-1;
145 curr_o_bps
= (wxUint8
)-1;
146 curr_o_stereo
= (bool)-1;
147 curr_i_srate
= (wxUint32
)-1;
148 curr_i_bps
= (wxUint8
)-1;
149 curr_i_stereo
= (bool)-1;
152 wxWinSound::~wxWinSound(void)
156 fragments
.WaitForAll();
159 waveOutReset(internal
->devout_id
);
161 waveInReset(internal
->devout_id
);
163 fragments
.FreeIOBuffer();
166 waveOutClose(internal
->devout_id
);
168 waveInClose(internal
->devin_id
);
170 if (internal
->sndWin
)
171 ::DestroyWindow(internal
->sndWin
);
176 bool wxWinSound::Wakeup(wxSndBuffer
& buf
)
178 if (!Reopen(buf
, FALSE
)) {
179 buf
.Clear(wxSND_BUFLOCKED
);
183 fragments
.OnBufferFinished(NULL
);
187 void wxWinSound::PrepareHeader(wxFragmentBuffer::wxFragBufPtr
& frag
,
193 if ((mode
== wxSND_INPUT
&& !win_opened
) ||
194 (mode
== wxSND_OUTPUT
&& !wout_opened
))
197 info
= new wxSndWinInfo
;
199 info
->h_data
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_SHARE
, MMD_WIN_IO_BSIZE
);
200 info
->h_hdr
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_SHARE
, sizeof(WAVEHDR
));
202 info
->data
= (char *)GlobalLock(info
->h_data
);
203 hdr
= info
->hdr
= (WAVEHDR
*)GlobalLock(info
->h_hdr
);
205 memset(hdr
, 0, sizeof(*hdr
));
206 hdr
->lpData
= info
->data
;
207 hdr
->dwBufferLength
= frag
.size
;
208 hdr
->dwUser
= (DWORD
)&frag
;
209 hdr
->dwFlags
= WHDR_DONE
;
211 if (mode
== wxSND_INPUT
) {
212 MMRESULT result
= waveInPrepareHeader(internal
->devin_id
, hdr
,
215 if (result
!= MMSYSERR_NOERROR
)
218 MMRESULT result
= waveOutPrepareHeader(internal
->devout_id
, hdr
,
220 if (result
!= MMSYSERR_NOERROR
)
224 frag
.sndbuf
= new wxStreamBuffer();
225 frag
.sndbuf
->SetBufferIO(info
->data
, info
->data
+ MMD_WIN_IO_BSIZE
);
226 frag
.user_data
= (char *)info
;
229 void wxWinSound::UnprepareHeader(wxFragmentBuffer::wxFragBufPtr
& frag
,
232 wxSndWinInfo
*info
= (wxSndWinInfo
*)frag
.user_data
;
234 if ((mode
== wxSND_INPUT
&& !win_opened
) ||
235 (mode
== wxSND_OUTPUT
&& !wout_opened
))
240 if (mode
== wxSND_INPUT
) {
241 result
= waveInUnprepareHeader(internal
->devin_id
, info
->hdr
, sizeof(*info
->hdr
));
243 result
= waveOutUnprepareHeader(internal
->devout_id
, info
->hdr
, sizeof(*info
->hdr
));
248 printf("unprepare = %d\n", result
);
250 GlobalUnlock(info
->h_hdr
);
251 GlobalUnlock(info
->h_data
);
253 GlobalFree(info
->h_hdr
);
254 GlobalFree(info
->h_data
);
259 extern char wxCanvasClassName
[];
261 LRESULT APIENTRY _EXPORT
wxSoundHandlerWndProc(HWND hWnd
, UINT message
,
262 WPARAM wParam
, LPARAM lParam
)
266 wxWinSound
*snd_drv
= (wxWinSound
*)GetWindowLong(hWnd
, GWL_USERDATA
);
267 WAVEHDR
*hdr
= (WAVEHDR
*)lParam
;
268 wxFragmentBuffer::wxFragBufPtr
*buf
=
269 (wxFragmentBuffer::wxFragBufPtr
*)hdr
->dwUser
;
272 hdr
->dwFlags
|= WHDR_DONE
;
274 snd_drv
->fragments
.OnBufferFinished(buf
);
278 printf("wave Open ack\n");
281 printf("wave Close ack\n");
285 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
290 void wxWinSound::StopBuffer(wxSndBuffer
& buf
)
293 buf
.Set(wxSND_BUFSTOP
);
294 fragments
.AbortBuffer(buf
);
297 while (buf
.IsSet(wxSND_BUFSTOP
))
301 bool wxWinSound::Reopen(wxSndBuffer
& buf
, bool force
)
303 WAVEFORMATEX wformat
;
305 if ((buf
.GetSampleRate() != curr_o_srate
) ||
306 (buf
.GetBps() != curr_o_bps
) ||
307 (buf
.GetStereo() != curr_o_stereo
) ||
308 (buf
.GetMode() != curr_mode
))
312 wxUint32
*curr_srate
=
313 (buf
.GetMode() == wxSND_OUTPUT
) ? &curr_o_srate
: &curr_i_srate
;
315 (buf
.GetMode() == wxSND_OUTPUT
) ? &curr_o_bps
: &curr_i_bps
;
317 (buf
.GetMode() == wxSND_OUTPUT
) ? &curr_o_stereo
: &curr_i_stereo
;
319 fragments
.WaitForAll();
320 fragments
.FreeIOBuffer();
322 if (!internal
->sndWin
) {
323 FARPROC proc
= MakeProcInstance((FARPROC
)wxSoundHandlerWndProc
, wxGetInstance());
325 internal
->sndWin
= ::CreateWindow(wxCanvasClassName
, NULL
, 0,
326 0, 0, 0, 0, NULL
, (HMENU
) NULL
,
329 ::SetWindowLong(internal
->sndWin
, GWL_WNDPROC
,
331 ::SetWindowLong(internal
->sndWin
, GWL_USERDATA
, (LONG
) this);
335 waveOutClose(internal
->devout_id
);
339 waveInClose(internal
->devin_id
);
343 *curr_srate
= buf
.GetSampleRate();
344 *curr_bps
= buf
.GetBps();
345 *curr_stereo
= buf
.GetStereo();
346 wformat
.wFormatTag
= WAVE_FORMAT_PCM
;
347 wformat
.nChannels
= curr_o_stereo
+1;
349 wformat
.nSamplesPerSec
= curr_o_srate
;
350 wformat
.nBlockAlign
= curr_o_bps
/ 8 * wformat
.nChannels
;
351 wformat
.nAvgBytesPerSec
=
352 wformat
.nSamplesPerSec
* wformat
.nBlockAlign
;
353 wformat
.wBitsPerSample
= curr_o_bps
;
356 if (buf
.GetMode() == wxSND_OUTPUT
) {
357 MMRESULT result
= waveOutOpen(&internal
->devout_id
,
358 WAVE_MAPPER
, &wformat
,
359 (DWORD
)internal
->sndWin
, (DWORD
)this,
361 if (result
!= MMSYSERR_NOERROR
)
363 internal
->devin_id
= 0;
365 curr_mode
= wxSND_OUTPUT
;
367 fragments
.AllocIOBuffer();
370 MMRESULT result
= waveInOpen(&internal
->devin_id
,
371 WAVE_MAPPER
, &wformat
,
372 (DWORD
)internal
->sndWin
, (DWORD
)this,
374 if (result
!= MMSYSERR_NOERROR
)
376 internal
->devout_id
= 0;
378 curr_mode
= wxSND_INPUT
;
380 fragments
.AllocIOBuffer();