]>
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
= m_optrs
= new wxFragBufPtr
[m_maxoq
];
46 m_lstiptrs
= m_iptrs
= new wxFragBufPtr
[m_maxiq
];
48 for (i
=0;i
<m_maxoq
;i
++) {
49 m_lstoptrs
[i
].size
= MMD_WIN_IO_BSIZE
;
50 m_lstoptrs
[i
].ptr
= 0;
51 m_lstoptrs
[i
].buffers
= new wxList();
52 m_lstoptrs
[i
].state
= wxBUFFER_FREE
;
54 w_snd
->PrepareHeader(m_lstoptrs
[i
], wxSND_OUTPUT
);
57 for (i
=0;i
<m_maxiq
;i
++) {
58 m_lstiptrs
[i
].size
= MMD_WIN_IO_BSIZE
;
59 m_lstiptrs
[i
].ptr
= 0;
60 m_lstiptrs
[i
].buffers
= new wxList();
61 m_lstiptrs
[i
].state
= wxBUFFER_FREE
;
63 w_snd
->PrepareHeader(m_lstiptrs
[i
], wxSND_INPUT
);
67 void wxSndWinFragment::FreeIOBuffer(void)
69 wxWinSound
*w_snd
= (wxWinSound
*)m_iodrv
;
72 if (!m_lstoptrs
&& !m_lstiptrs
)
75 for (i
=0;i
<m_maxoq
;i
++) {
76 w_snd
->UnprepareHeader(m_lstoptrs
[i
], wxSND_OUTPUT
);
77 delete m_lstoptrs
[i
].buffers
;
80 for (i
=0;i
<m_maxiq
;i
++) {
81 w_snd
->UnprepareHeader(m_lstiptrs
[i
], wxSND_INPUT
);
82 delete m_lstiptrs
[i
].buffers
;
88 m_lstoptrs
= m_lstiptrs
= NULL
;
89 m_maxoq
= m_maxiq
= 0;
92 void wxSndWinFragment::WaitForAll()
102 for (i
=0;i
<m_maxoq
;i
++) {
103 if (m_lstoptrs
[i
].state
== wxBUFFER_FFILLED
) {
115 bool wxSndWinFragment::OnBufferFilled(wxFragBufPtr
*ptr
, wxSndMode mode
)
117 wxSndWinInfo
*info
= (wxSndWinInfo
*)ptr
->user_data
;
118 wxWinSound
*w_snd
= (wxWinSound
*)m_iodrv
;
123 result
= waveInAddBuffer(w_snd
->internal
->devin_id
, info
->hdr
,
127 result
= waveOutWrite(w_snd
->internal
->devout_id
, info
->hdr
,
129 printf("WINOUT: result=%d\n", result
);
135 wxWinSound::wxWinSound(void)
139 internal
= new wxWinSoundInternal
;
140 internal
->devout_id
= 0;
141 internal
->devin_id
= 0;
142 internal
->sndWin
= 0;
146 curr_o_srate
= (wxUint32
)-1;
147 curr_o_bps
= (wxUint8
)-1;
148 curr_o_stereo
= (bool)-1;
149 curr_i_srate
= (wxUint32
)-1;
150 curr_i_bps
= (wxUint8
)-1;
151 curr_i_stereo
= (bool)-1;
154 wxWinSound::~wxWinSound(void)
158 fragments
.WaitForAll();
161 waveOutReset(internal
->devout_id
);
163 waveInReset(internal
->devout_id
);
165 fragments
.FreeIOBuffer();
168 waveOutClose(internal
->devout_id
);
170 waveInClose(internal
->devin_id
);
172 if (internal
->sndWin
)
173 ::DestroyWindow(internal
->sndWin
);
178 bool wxWinSound::Wakeup(wxSndBuffer
& buf
)
180 if (!Reopen(buf
, FALSE
)) {
181 buf
.Clear(wxSND_BUFLOCKED
);
185 fragments
.OnBufferFinished(NULL
);
189 void wxWinSound::PrepareHeader(wxFragmentBuffer::wxFragBufPtr
& frag
,
195 if ((mode
== wxSND_INPUT
&& !win_opened
) ||
196 (mode
== wxSND_OUTPUT
&& !wout_opened
))
199 info
= new wxSndWinInfo
;
201 info
->h_data
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_SHARE
, frag
.size
);
202 info
->h_hdr
= GlobalAlloc(GMEM_MOVEABLE
| GMEM_SHARE
, sizeof(WAVEHDR
));
204 info
->data
= (char *)GlobalLock(info
->h_data
);
205 hdr
= info
->hdr
= (WAVEHDR
*)GlobalLock(info
->h_hdr
);
207 memset(hdr
, 0, sizeof(*hdr
));
208 hdr
->lpData
= info
->data
;
209 hdr
->dwBufferLength
= frag
.size
;
210 hdr
->dwUser
= (DWORD
)&frag
;
211 hdr
->dwFlags
= WHDR_DONE
;
213 if (mode
== wxSND_INPUT
) {
214 MMRESULT result
= waveInPrepareHeader(internal
->devin_id
, hdr
,
217 printf("prepareIn = %d\n", result
);
218 if (result
!= MMSYSERR_NOERROR
)
221 MMRESULT result
= waveOutPrepareHeader(internal
->devout_id
, hdr
,
223 printf("prepareOut = %d\n", result
);
224 if (result
!= MMSYSERR_NOERROR
)
228 frag
.user_data
= (char *)info
;
229 frag
.data
= info
->data
;
232 void wxWinSound::UnprepareHeader(wxFragmentBuffer::wxFragBufPtr
& frag
,
235 wxSndWinInfo
*info
= (wxSndWinInfo
*)frag
.user_data
;
237 if ((mode
== wxSND_INPUT
&& !win_opened
) ||
238 (mode
== wxSND_OUTPUT
&& !wout_opened
))
243 if (mode
== wxSND_INPUT
) {
244 result
= waveInUnprepareHeader(internal
->devin_id
, info
->hdr
, sizeof(*info
->hdr
));
246 result
= waveOutUnprepareHeader(internal
->devout_id
, info
->hdr
, sizeof(*info
->hdr
));
249 printf("unprepare = %d\n", result
);
251 GlobalUnlock(info
->h_hdr
);
252 GlobalUnlock(info
->h_data
);
254 GlobalFree(info
->h_hdr
);
255 GlobalFree(info
->h_data
);
260 extern char wxCanvasClassName
[];
262 LRESULT APIENTRY _EXPORT
wxSoundHandlerWndProc(HWND hWnd
, UINT message
,
263 WPARAM wParam
, LPARAM lParam
)
267 wxWinSound
*snd_drv
= (wxWinSound
*)GetWindowLong(hWnd
, GWL_USERDATA
);
268 WAVEHDR
*hdr
= (WAVEHDR
*)lParam
;
269 wxFragmentBuffer::wxFragBufPtr
*buf
=
270 (wxFragmentBuffer::wxFragBufPtr
*)hdr
->dwUser
;
273 hdr
->dwFlags
|= WHDR_DONE
;
275 snd_drv
->fragments
.OnBufferFinished(buf
);
279 printf("wave Open ack\n");
282 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();