]> git.saurik.com Git - wxWidgets.git/blame - utils/wxMMedia2/lib/sndwin.cpp
added support for several new events in wxCalendarCtrl: clicking on week
[wxWidgets.git] / utils / wxMMedia2 / lib / sndwin.cpp
CommitLineData
503aa33d
GL
1// --------------------------------------------------------------------------
2// Name: sndwin.cpp
3// Purpose:
4// Date: 08/11/1999
5// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
6// CVSID: $Id$
7// --------------------------------------------------------------------------
8#include <wx/wxprec.h>
9
7f45dffc 10#include <wx/app.h>
503aa33d 11#include <wx/module.h>
7f45dffc 12#include <wx/msw/private.h>
503aa33d
GL
13#include <string.h>
14#include "sndbase.h"
15#include "sndwin.h"
16#include "sndpcm.h"
17
18#include <windows.h>
19#include <mmsystem.h>
20
21typedef struct _wxSoundInternal wxSoundInternal;
22typedef struct _wxSoundInfoHeader wxSoundInfoHeader;
23
e3367904 24extern const wxChar *wxCanvasClassName;
503aa33d
GL
25
26wxList *wxSoundHandleList = NULL;
27
28static inline wxSoundStreamWin *wxFindSoundFromHandle(WXHWND hWnd)
29{
30 wxNode *node = wxSoundHandleList->Find((long)hWnd);
31 if (!node)
32 return NULL;
33 return (wxSoundStreamWin *)node->Data();
34}
35
36struct _wxSoundInternal {
37 HWND m_sndWin;
38 HWAVEIN m_devin;
39 HWAVEOUT m_devout;
40 bool m_output_enabled, m_input_enabled;
41};
42
43struct _wxSoundInfoHeader {
44 HGLOBAL m_h_header, m_h_data;
45 char *m_data;
46 WAVEHDR *m_header;
47 int m_mode;
48 bool m_playing, m_recording;
49 wxUint32 m_position, m_size;
50
51 wxSoundStreamWin *m_driver;
52};
53
56dc1ffd 54#define WXSOUND_MAX_QUEUE 10
503aa33d
GL
55
56wxSoundStreamWin::wxSoundStreamWin()
57{
58 wxSoundFormatPcm pcm;
59
60 m_production_started = FALSE;
61 m_internal = new wxSoundInternal;
62 m_snderror = wxSOUND_NOERR;
63
64 // Setup defaults
65 CreateSndWindow();
66 SetSoundFormat(pcm);
67
cc82835c
GL
68 m_internal->m_input_enabled = FALSE;
69 m_internal->m_output_enabled = FALSE;
70
e3367904
GL
71 m_waiting_for = FALSE;
72
503aa33d
GL
73 if (!OpenDevice(wxSOUND_OUTPUT))
74 return;
75
76 CloseDevice();
77}
78
79wxSoundStreamWin::~wxSoundStreamWin()
80{
81 if (m_production_started)
82 StopProduction();
83 DestroySndWindow();
84
85 delete m_internal;
86}
87
88LRESULT APIENTRY _EXPORT _wxSoundHandlerWndProc(HWND hWnd, UINT message,
89 WPARAM wParam, LPARAM lParam)
90{
cc82835c
GL
91 wxSoundStreamWin *sndwin;
92
93 sndwin = wxFindSoundFromHandle((WXHWND)hWnd);
94 if (!sndwin)
95 return (LRESULT)0;
96
503aa33d 97 switch (message) {
56dc1ffd 98 case MM_WOM_DONE:
cc82835c 99 sndwin->NotifyDoneBuffer(wParam, wxSOUND_OUTPUT);
56dc1ffd
GL
100 break;
101 case MM_WIM_DATA:
cc82835c 102 sndwin->NotifyDoneBuffer(wParam, wxSOUND_INPUT);
503aa33d 103 break;
503aa33d
GL
104 default:
105 break;
106 }
107 return (LRESULT)0;
108}
109
7f45dffc
GL
110// -----------------------------------------------------------------------
111// CreateSndWindow() creates an hidden window which will receive the sound
112// events
113// -----------------------------------------------------------------------
114
503aa33d
GL
115void wxSoundStreamWin::CreateSndWindow()
116{
117 FARPROC proc = MakeProcInstance((FARPROC)_wxSoundHandlerWndProc,
118 wxGetInstance());
119 int error;
120
121 m_internal->m_sndWin = ::CreateWindow(wxCanvasClassName, NULL, 0,
122 0, 0, 0, 0, NULL, (HMENU) NULL,
123 wxGetInstance(), NULL);
124
125 error = GetLastError();
503aa33d
GL
126
127 ::SetWindowLong(m_internal->m_sndWin, GWL_WNDPROC, (LONG)proc);
128
7f45dffc
GL
129 // Add this window to the sound handle list so we'll be able to redecode
130 // the "magic" number.
503aa33d
GL
131 wxSoundHandleList->Append((long)m_internal->m_sndWin, (wxObject *)this);
132}
133
7f45dffc
GL
134// -----------------------------------------------------------------------
135// DestroySndWindow() destroys the hidden window
136// -----------------------------------------------------------------------
137
503aa33d
GL
138void wxSoundStreamWin::DestroySndWindow()
139{
140 if (m_internal->m_sndWin) {
141 ::DestroyWindow(m_internal->m_sndWin);
142 wxSoundHandleList->DeleteObject((wxObject *)this);
143 }
144}
145
7f45dffc
GL
146// -------------------------------------------------------------------------
147// OpenDevice(int mode) initializes the windows driver for a "mode"
148// operation. mode is a bit mask: if the bit "wxSOUND_OUTPUT" is set,
149// the driver is opened for output operation, and if the bit "wxSOUND_INPUT"
150// is set, then the driver is opened for input operation. The two modes
151// aren't exclusive.
152// The initialization parameters (sample rate, ...) are taken from the
153// m_sndformat object.
154// At the end, OpenDevice() calls AllocHeaders() to initialize the Sound IO
155// queue.
156// -------------------------------------------------------------------------
503aa33d
GL
157bool wxSoundStreamWin::OpenDevice(int mode)
158{
159 wxSoundFormatPcm *pcm;
160 WAVEFORMATEX wformat;
161
162 if (!m_sndformat) {
163 m_snderror = wxSOUND_INVFRMT;
164 return FALSE;
165 }
166
167 pcm = (wxSoundFormatPcm *)m_sndformat;
168
169 wformat.wFormatTag = WAVE_FORMAT_PCM;
170 wformat.nChannels = pcm->GetChannels();
56dc1ffd 171 wformat.nBlockAlign = wformat.nChannels * pcm->GetBPS() / 8;
503aa33d 172 wformat.nSamplesPerSec = pcm->GetSampleRate();
56dc1ffd 173 wformat.nAvgBytesPerSec = wformat.nSamplesPerSec * wformat.nBlockAlign;
503aa33d
GL
174 wformat.wBitsPerSample = pcm->GetBPS();
175 wformat.cbSize = 0;
176
7f45dffc
GL
177 // -----------------------------------
178 // Open the driver for Output operation
179 // -----------------------------------
503aa33d
GL
180 if (mode & wxSOUND_OUTPUT) {
181 MMRESULT result;
182
183 result = waveOutOpen(&m_internal->m_devout,
184 WAVE_MAPPER, &wformat,
185 (DWORD)m_internal->m_sndWin, 0,
186 CALLBACK_WINDOW);
187
188 if (result != MMSYSERR_NOERROR) {
189 m_snderror = wxSOUND_INVDEV;
190 return FALSE;
191 }
192
193 m_output_frag_out = WXSOUND_MAX_QUEUE-1;
194 m_current_frag_out = 0;
195
196 m_internal->m_output_enabled = TRUE;
197 }
7f45dffc
GL
198 // -----------------------------------
199 // Open the driver for Input operation
200 // -----------------------------------
503aa33d
GL
201 if (mode & wxSOUND_INPUT) {
202 MMRESULT result;
203
204 result = waveInOpen(&m_internal->m_devin,
205 WAVE_MAPPER, &wformat,
206 (DWORD)m_internal->m_sndWin, 0,
207 CALLBACK_WINDOW);
208
209 if (result != MMSYSERR_NOERROR) {
210 m_snderror = wxSOUND_INVDEV;
211 return FALSE;
212 }
213
e3367904
GL
214 m_current_frag_in = WXSOUND_MAX_QUEUE-1;
215 m_input_frag_in = 0;
503aa33d
GL
216
217 m_internal->m_input_enabled = TRUE;
218 }
219
56dc1ffd
GL
220 if (mode & wxSOUND_OUTPUT) {
221 if (!AllocHeaders(wxSOUND_OUTPUT)) {
222 CloseDevice();
223 return FALSE;
224 }
503aa33d 225 }
56dc1ffd
GL
226 if (mode & wxSOUND_INPUT) {
227 if (!AllocHeaders(wxSOUND_INPUT)) {
228 CloseDevice();
229 return FALSE;
230 }
231 }
232
503aa33d
GL
233 return TRUE;
234}
235
7f45dffc
GL
236// -------------------------------------------------------------------------
237// CloseDevice() closes the driver handles and frees memory allocated for
238// IO queues.
239// -------------------------------------------------------------------------
503aa33d
GL
240void wxSoundStreamWin::CloseDevice()
241{
242 if (m_internal->m_output_enabled) {
56dc1ffd 243 FreeHeaders(wxSOUND_OUTPUT);
e3367904 244 m_internal->m_output_enabled = FALSE;
503aa33d
GL
245 waveOutClose(m_internal->m_devout);
246 }
247
248 if (m_internal->m_input_enabled) {
56dc1ffd 249 FreeHeaders(wxSOUND_INPUT);
e3367904 250 m_internal->m_input_enabled = FALSE;
503aa33d
GL
251 waveInClose(m_internal->m_devin);
252 }
503aa33d
GL
253}
254
7f45dffc
GL
255// -------------------------------------------------------------------------
256// AllocHeader(int mode)
257//
258// mode has the same mean as in OpenDevice() except that here the two flags
259// must be exclusive.
260// AllocHeader() initializes an element of an operation (this can be input
261// or output). It means it allocates the sound header's memory block
262// and "prepares" it (It is needed by Windows). At the same time, it sets
263// private datas so we can the header's owner (See callback).
264//
265// It returns the new allocated block or NULL.
266// -------------------------------------------------------------------------
503aa33d
GL
267wxSoundInfoHeader *wxSoundStreamWin::AllocHeader(int mode)
268{
269 wxSoundInfoHeader *info;
270 WAVEHDR *header;
271
7f45dffc 272 // Some memory allocation
503aa33d
GL
273 info = new wxSoundInfoHeader;
274 info->m_h_data = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, GetBestSize());
275 info->m_h_header = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR));
276 if (!info->m_h_data || !info->m_h_header) {
277 delete info;
278 m_snderror = wxSOUND_MEMERR;
279 return NULL;
280 }
281
7f45dffc 282 // Get the two pointers from the system
503aa33d
GL
283 info->m_data = (char *)GlobalLock(info->m_h_data);
284 info->m_header = (WAVEHDR *)GlobalLock(info->m_h_header);
7f45dffc 285 // Set the header's mode
503aa33d 286 info->m_mode = mode;
7f45dffc 287 // Set the parent of the header
503aa33d 288 info->m_driver = this;
7f45dffc 289 // Clean it up
503aa33d
GL
290 ClearHeader(info);
291
292 header = info->m_header;
7f45dffc 293 // Initialize Windows variables
503aa33d
GL
294 header->lpData = info->m_data;
295 header->dwBufferLength = GetBestSize();
296 header->dwUser = (DWORD)info;
297 header->dwFlags = WHDR_DONE;
298
7f45dffc 299 // "Prepare" the header
503aa33d
GL
300 if (mode == wxSOUND_INPUT) {
301 MMRESULT result;
302
303 result = waveInPrepareHeader(m_internal->m_devin, header,
304 sizeof(WAVEHDR));
305
306 if (result != MMSYSERR_NOERROR) {
7f45dffc 307 // If something goes wrong, free everything.
503aa33d
GL
308 GlobalUnlock(info->m_data);
309 GlobalUnlock(info->m_header);
310 GlobalFree(info->m_h_data);
311 GlobalFree(info->m_h_header);
312 delete info;
313
314 m_snderror = wxSOUND_IOERR;
315 return NULL;
316 }
317 } else if (mode == wxSOUND_OUTPUT) {
318 MMRESULT result;
319
320 result = waveOutPrepareHeader(m_internal->m_devout, header,
321 sizeof(WAVEHDR));
322
323 if (result != MMSYSERR_NOERROR) {
7f45dffc 324 // If something goes wrong, free everything.
503aa33d
GL
325 GlobalUnlock(info->m_data);
326 GlobalUnlock(info->m_header);
327 GlobalFree(info->m_h_data);
328 GlobalFree(info->m_h_header);
329 delete info;
330
331 m_snderror = wxSOUND_IOERR;
332 return NULL;
333 }
334 }
335 return info;
336}
337
7f45dffc
GL
338// -------------------------------------------------------------------------
339// AllocHeaders(int mode)
340//
341// "mode" has the same mean as for OpenDevice() except that the two flags must
342// be exclusive.
343// AllocHeaders() allocates WXSOUND_MAX_QUEUE (= 128) blocks for an operation
344// queue. It uses AllocHeader() for each element.
345//
346// Once it has allocated all blocks, it returns TRUE and if an error occured
347// it returns FALSE.
348// -------------------------------------------------------------------------
503aa33d
GL
349bool wxSoundStreamWin::AllocHeaders(int mode)
350{
351 int i;
352 wxSoundInfoHeader **headers;
353
354 if (mode == wxSOUND_OUTPUT)
355 headers = m_headers_play = new wxSoundInfoHeader *[WXSOUND_MAX_QUEUE];
356 else
357 headers = m_headers_rec = new wxSoundInfoHeader *[WXSOUND_MAX_QUEUE];
358
359 memset(headers, 0, WXSOUND_MAX_QUEUE*sizeof(wxSoundInfoHeader *));
360
361 for (i=0;i<WXSOUND_MAX_QUEUE;i++) {
362 headers[i] = AllocHeader(mode);
363 if (!headers[i]) {
364 FreeHeaders(mode);
365 return FALSE;
366 }
367 }
368 return TRUE;
369}
370
7f45dffc
GL
371// -------------------------------------------------------------------------
372// FreeHeader(int mode)
373//
374// "mode" has the same mean as for OpenDevice() except that the two flags must
375// be exclusive.
376// FreeHeader() frees a memory block and "unprepares" it.
377// -------------------------------------------------------------------------
503aa33d
GL
378void wxSoundStreamWin::FreeHeader(wxSoundInfoHeader *header, int mode)
379{
380 if (mode == wxSOUND_OUTPUT)
381 waveOutUnprepareHeader(m_internal->m_devout, header->m_header, sizeof(WAVEHDR));
382 else
383 waveInUnprepareHeader(m_internal->m_devin, header->m_header, sizeof(WAVEHDR));
384
385 GlobalUnlock(header->m_data);
386 GlobalUnlock(header->m_header);
387 GlobalFree(header->m_h_header);
388 GlobalFree(header->m_h_data);
389 delete header;
390}
391
7f45dffc
GL
392// -------------------------------------------------------------------------
393// FreeHeaders(int mode)
394//
395// "mode" has the same mean as for OpenDevice() except that the two flags must
396// be exclusive.
397// FreeHeaders() frees all an operation queue once it has checked that
398// all buffers have been terminated.
399// -------------------------------------------------------------------------
503aa33d
GL
400void wxSoundStreamWin::FreeHeaders(int mode)
401{
402 int i;
403 wxSoundInfoHeader ***headers;
404
405 if (mode == wxSOUND_OUTPUT)
406 headers = &m_headers_play;
407 else
408 headers = &m_headers_rec;
409
410 for (i=0;i<WXSOUND_MAX_QUEUE;i++) {
411 if ((*headers)[i]) {
7f45dffc 412 // We wait for the end of the buffer
503aa33d 413 WaitFor((*headers)[i]);
7f45dffc 414 // Then, we free the header
503aa33d
GL
415 FreeHeader((*headers)[i], mode);
416 }
417 }
418 delete[] (*headers);
419 (*headers) = NULL;
420}
421
7f45dffc
GL
422// -------------------------------------------------------------------------
423// WaitFor(wxSoundInfoHeader *info)
424//
425// "info" is one element of an IO queue
426// WaitFor() checks whether the specified block has been terminated.
427// If it hasn't been terminated, it waits for its termination.
428//
429// NB: if it's a partially filled buffer it adds it to the Windows queue
430// -------------------------------------------------------------------------
503aa33d
GL
431void wxSoundStreamWin::WaitFor(wxSoundInfoHeader *info)
432{
7f45dffc 433 // If the buffer is finished, we return immediately
56dc1ffd
GL
434 if (!info->m_playing) {
435
436 // We begun filling it: we must send it to the Windows queue
437 if (info->m_position != 0) {
438 memset(info->m_data + info->m_position, 0, info->m_size);
439 AddToQueue(info);
440 }
e3367904 441 }
56dc1ffd 442
e3367904
GL
443 if (m_waiting_for) {
444 // PROBLEM //
503aa33d 445 return;
56dc1ffd 446 }
e3367904 447 m_waiting_for = TRUE;
7f45dffc 448 // Else, we wait for its termination
503aa33d
GL
449 while (info->m_playing || info->m_recording)
450 wxYield();
e3367904 451 m_waiting_for = FALSE;
503aa33d
GL
452}
453
7f45dffc
GL
454// -------------------------------------------------------------------------
455// AddToQueue(wxSoundInfoHeader *info)
456//
457// For "info", see WaitFor()
458// AddToQueue() sends the IO queue element to the Windows queue.
459//
460// Warning: in the current implementation, it partially assume we send the
461// element in the right order. This is true in that implementation but if
462// you use it elsewhere, be careful: it may shuffle all your sound datas.
463// -------------------------------------------------------------------------
503aa33d
GL
464bool wxSoundStreamWin::AddToQueue(wxSoundInfoHeader *info)
465{
466 MMRESULT result;
467
468 if (info->m_mode == wxSOUND_INPUT) {
7f45dffc 469 // Increment the input fragment pointer
503aa33d
GL
470 result = waveInAddBuffer(m_internal->m_devin,
471 info->m_header, sizeof(WAVEHDR));
472 if (result == MMSYSERR_NOERROR)
473 info->m_recording = TRUE;
474 else
475 return FALSE;
476 } else if (info->m_mode == wxSOUND_OUTPUT) {
477 result = waveOutWrite(m_internal->m_devout,
478 info->m_header, sizeof(WAVEHDR));
479 if (result == MMSYSERR_NOERROR)
480 info->m_playing = TRUE;
481 else
482 return FALSE;
483 }
484 return TRUE;
485}
486
7f45dffc
GL
487// -------------------------------------------------------------------------
488// ClearHeader(wxSoundInfoHeader *info)
489//
490// ClearHeader() reinitializes the parameters of "info" to their default
491// value.
492// -------------------------------------------------------------------------
503aa33d
GL
493void wxSoundStreamWin::ClearHeader(wxSoundInfoHeader *info)
494{
495 info->m_playing = FALSE;
496 info->m_recording = FALSE;
497 info->m_position = 0;
498 info->m_size = GetBestSize();
499}
500
7f45dffc
GL
501// -------------------------------------------------------------------------
502// wxSoundInfoHeader *NextFragmentOutput()
503//
504// NextFragmentOutput() looks for a free output block. It will always
505// return you a non-NULL pointer but it may waits for an empty buffer a long
506// time.
507// -------------------------------------------------------------------------
503aa33d
GL
508wxSoundInfoHeader *wxSoundStreamWin::NextFragmentOutput()
509{
510 if (m_headers_play[m_current_frag_out]->m_playing) {
511 m_current_frag_out = (m_current_frag_out + 1) % WXSOUND_MAX_QUEUE;
512
513 if (m_headers_play[m_current_frag_out]->m_playing)
514 WaitFor(m_headers_play[m_current_frag_out]);
515 }
516 if (m_current_frag_out == m_output_frag_out)
517 m_queue_filled = TRUE;
518 return m_headers_play[m_current_frag_out];
519}
520
7f45dffc
GL
521// -------------------------------------------------------------------------
522// The behaviour of Write is documented in the global documentation.
523// -------------------------------------------------------------------------
0662cd32 524wxSoundStream& wxSoundStreamWin::Write(const void *buffer, wxUint32 len)
503aa33d
GL
525{
526 m_lastcount = 0;
527 if (!m_internal->m_output_enabled)
528 return *this;
529
530 while (len > 0) {
531 wxSoundInfoHeader *header;
0662cd32 532 wxUint32 to_copy;
503aa33d 533
7f45dffc 534 // Get a new output fragment
503aa33d
GL
535 header = NextFragmentOutput();
536
537 to_copy = (len > header->m_size) ? header->m_size : len;
538 memcpy(header->m_data + header->m_position, buffer, to_copy);
539
540 header->m_position += to_copy;
541 header->m_size -= to_copy;
542 buffer = (((const char *)buffer) + to_copy);
543 len -= to_copy;
544 m_lastcount += to_copy;
545
7f45dffc 546 // If the fragment is full, we send it to the Windows queue.
503aa33d
GL
547 if (header->m_size == 0)
548 if (!AddToQueue(header)) {
549 m_snderror = wxSOUND_IOERR;
550 return *this;
551 }
552 }
553 return *this;
554}
555
7f45dffc
GL
556// -------------------------------------------------------------------------
557// NextFragmentInput is not functional.
558// -------------------------------------------------------------------------
503aa33d
GL
559wxSoundInfoHeader *wxSoundStreamWin::NextFragmentInput()
560{
561 wxSoundInfoHeader *header;
562
cc82835c
GL
563 m_current_frag_in = (m_current_frag_in + 1) % WXSOUND_MAX_QUEUE;
564
503aa33d 565 header = m_headers_rec[m_current_frag_in];
56dc1ffd
GL
566 if (header->m_recording)
567 WaitFor(header);
568
503aa33d
GL
569 if (m_current_frag_in == m_input_frag_in)
570 m_queue_filled = TRUE;
571
572 return header;
573}
574
7f45dffc
GL
575// -------------------------------------------------------------------------
576// The behaviour of Read is documented in the global documentation.
577// -------------------------------------------------------------------------
0662cd32 578wxSoundStream& wxSoundStreamWin::Read(void *buffer, wxUint32 len)
503aa33d
GL
579{
580 wxSoundInfoHeader *header;
0662cd32 581 wxUint32 to_copy;
503aa33d
GL
582
583 m_lastcount = 0;
584 if (!m_internal->m_input_enabled)
585 return *this;
586
587 while (len > 0) {
588 header = NextFragmentInput();
589
590 to_copy = (len > header->m_size) ? header->m_size : len;
591 memcpy(buffer, header->m_data + header->m_position, to_copy);
592
593 header->m_position += to_copy;
594 header->m_size -= to_copy;
595 buffer = (((char *)buffer) + to_copy);
596 len -= to_copy;
597 m_lastcount += to_copy;
598
599 if (header->m_size == 0) {
600 ClearHeader(header);
601 if (!AddToQueue(header)) {
602 m_snderror = wxSOUND_IOERR;
603 return *this;
604 }
605 }
606 }
607 return *this;
608}
609
7f45dffc
GL
610// -------------------------------------------------------------------------
611// NotifyDoneBuffer(wxUint32 dev_handle)
612//
613// NotifyDoneBuffer() is called by wxSoundHandlerProc each time a sound
614// fragment finished. It reinitializes the parameters of the fragment and
615// sends an event to the clients.
616// -------------------------------------------------------------------------
56dc1ffd 617void wxSoundStreamWin::NotifyDoneBuffer(wxUint32 dev_handle, int flag)
503aa33d
GL
618{
619 wxSoundInfoHeader *info;
620
56dc1ffd
GL
621 if (flag == wxSOUND_OUTPUT) {
622 if (!m_internal->m_output_enabled)
623 return;
624
503aa33d
GL
625 m_output_frag_out = (m_output_frag_out + 1) % WXSOUND_MAX_QUEUE;
626 info = m_headers_play[m_output_frag_out];
627 ClearHeader(info);
628 m_queue_filled = FALSE;
e3367904
GL
629 if (!m_waiting_for)
630 OnSoundEvent(wxSOUND_OUTPUT);
503aa33d 631 } else {
56dc1ffd
GL
632 if (!m_internal->m_input_enabled)
633 return;
634
56dc1ffd 635 m_headers_rec[m_input_frag_in]->m_recording = FALSE;
e3367904
GL
636 m_input_frag_in = (m_input_frag_in + 1) % WXSOUND_MAX_QUEUE;
637 if (!m_waiting_for)
638 OnSoundEvent(wxSOUND_INPUT);
503aa33d
GL
639 m_queue_filled = FALSE;
640 }
641}
642
7f45dffc
GL
643// -------------------------------------------------------------------------
644// -------------------------------------------------------------------------
503aa33d
GL
645bool wxSoundStreamWin::SetSoundFormat(wxSoundFormatBase& base)
646{
647 return wxSoundStream::SetSoundFormat(base);
648}
649
7f45dffc
GL
650// -------------------------------------------------------------------------
651// -------------------------------------------------------------------------
503aa33d
GL
652bool wxSoundStreamWin::StartProduction(int evt)
653{
654 if ((m_internal->m_output_enabled && (evt & wxSOUND_OUTPUT)) ||
655 (m_internal->m_input_enabled && (evt & wxSOUND_INPUT)))
656 CloseDevice();
657
658 if (!OpenDevice(evt))
659 return FALSE;
660
661 m_production_started = TRUE;
662 m_queue_filled = FALSE;
663 // Send a dummy event to start.
664 if (evt & wxSOUND_OUTPUT)
e3367904 665 OnSoundEvent(wxSOUND_OUTPUT);
503aa33d
GL
666
667 if (evt & wxSOUND_INPUT) {
668 int i;
669 for (i=0;i<WXSOUND_MAX_QUEUE;i++)
670 AddToQueue(m_headers_rec[i]);
56dc1ffd
GL
671
672 waveInStart(m_internal->m_devin);
503aa33d
GL
673 }
674
675 return TRUE;
676}
677
7f45dffc
GL
678// -------------------------------------------------------------------------
679// -------------------------------------------------------------------------
503aa33d
GL
680bool wxSoundStreamWin::StopProduction()
681{
682 m_production_started = FALSE;
683 CloseDevice();
684 return TRUE;
685}
686
7f45dffc
GL
687// -------------------------------------------------------------------------
688// -------------------------------------------------------------------------
503aa33d
GL
689bool wxSoundStreamWin::QueueFilled() const
690{
691 return (!m_production_started || m_queue_filled);
692}
693
694
695// --------------------------------------------------------------------------
696// wxSoundWinModule
697// --------------------------------------------------------------------------
698
699class WXDLLEXPORT wxSoundWinModule : public wxModule {
700 DECLARE_DYNAMIC_CLASS(wxSoundWinModule)
701 public:
702 bool OnInit();
703 void OnExit();
704};
705
706IMPLEMENT_DYNAMIC_CLASS(wxSoundWinModule, wxModule)
707
708bool wxSoundWinModule::OnInit() {
709 wxSoundHandleList = new wxList(wxKEY_INTEGER);
710 return TRUE;
711}
712
713void wxSoundWinModule::OnExit() {
714 delete wxSoundHandleList;
715}