Reset the ALSA device if the number of available samples grows too large
[openal-soft/android.git] / Alc / backends / winmm.c
blob1af5105beb3241ac3192ff6d7a98172f36323db8
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <memory.h>
27 #include <windows.h>
28 #include <mmsystem.h>
30 #include "alMain.h"
31 #include "AL/al.h"
32 #include "AL/alc.h"
35 typedef struct {
36 // MMSYSTEM Device
37 volatile ALboolean bWaveShutdown;
38 HANDLE hWaveThreadEvent;
39 HANDLE hWaveThread;
40 DWORD ulWaveThreadID;
41 LONG lWaveBuffersCommitted;
42 WAVEHDR WaveBuffer[4];
44 union {
45 HWAVEIN In;
46 HWAVEOUT Out;
47 } hWaveHandle;
49 ALuint Frequency;
51 RingBuffer *pRing;
52 } WinMMData;
55 static const ALCchar woDefault[] = "WaveOut Default";
57 static ALCchar **PlaybackDeviceList;
58 static ALuint NumPlaybackDevices;
59 static ALCchar **CaptureDeviceList;
60 static ALuint NumCaptureDevices;
63 static void ProbePlaybackDevices(void)
65 ALuint i;
67 for(i = 0;i < NumPlaybackDevices;i++)
68 free(PlaybackDeviceList[i]);
70 NumPlaybackDevices = waveOutGetNumDevs();
71 PlaybackDeviceList = realloc(PlaybackDeviceList, sizeof(ALCchar*) * NumPlaybackDevices);
72 for(i = 0;i < NumPlaybackDevices;i++)
74 WAVEOUTCAPS WaveCaps;
76 PlaybackDeviceList[i] = NULL;
77 if(waveOutGetDevCaps(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
79 char name[1024];
80 ALuint count, j;
82 count = 0;
83 do {
84 if(count == 0)
85 snprintf(name, sizeof(name), "%s", WaveCaps.szPname);
86 else
87 snprintf(name, sizeof(name), "%s #%d", WaveCaps.szPname, count+1);
88 count++;
90 for(j = 0;j < i;j++)
92 if(strcmp(name, PlaybackDeviceList[j]) == 0)
93 break;
95 } while(j != i);
97 PlaybackDeviceList[i] = strdup(name);
102 static void ProbeCaptureDevices(void)
104 ALuint i;
106 for(i = 0;i < NumCaptureDevices;i++)
107 free(CaptureDeviceList[i]);
109 NumCaptureDevices = waveInGetNumDevs();
110 CaptureDeviceList = realloc(CaptureDeviceList, sizeof(ALCchar*) * NumCaptureDevices);
111 for(i = 0;i < NumCaptureDevices;i++)
113 WAVEINCAPS WaveInCaps;
115 CaptureDeviceList[i] = NULL;
116 if(waveInGetDevCaps(i, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR)
118 char name[1024];
119 ALuint count, j;
121 count = 0;
122 do {
123 if(count == 0)
124 snprintf(name, sizeof(name), "%s", WaveInCaps.szPname);
125 else
126 snprintf(name, sizeof(name), "%s #%d", WaveInCaps.szPname, count+1);
127 count++;
129 for(j = 0;j < i;j++)
131 if(strcmp(name, CaptureDeviceList[j]) == 0)
132 break;
134 } while(j != i);
136 CaptureDeviceList[i] = strdup(name);
143 WaveOutProc
145 Posts a message to 'PlaybackThreadProc' everytime a WaveOut Buffer is completed and
146 returns to the application (for more data)
148 static void CALLBACK WaveOutProc(HWAVEOUT hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2)
150 ALCdevice *pDevice = (ALCdevice*)dwInstance;
151 WinMMData *pData = pDevice->ExtraData;
153 (void)hDevice;
154 (void)dwParam2;
156 if(uMsg != WOM_DONE)
157 return;
159 // Decrement number of buffers in use
160 InterlockedDecrement(&pData->lWaveBuffersCommitted);
162 if(pData->bWaveShutdown == AL_FALSE)
164 // Notify Wave Processor Thread that a Wave Header has returned
165 PostThreadMessage(pData->ulWaveThreadID, uMsg, 0, dwParam1);
167 else
169 if(pData->lWaveBuffersCommitted == 0)
171 // Post 'Quit' Message to WaveOut Processor Thread
172 PostThreadMessage(pData->ulWaveThreadID, WM_QUIT, 0, 0);
178 PlaybackThreadProc
180 Used by "MMSYSTEM" Device. Called when a WaveOut buffer has used up its
181 audio data.
183 static DWORD WINAPI PlaybackThreadProc(LPVOID lpParameter)
185 ALCdevice *pDevice = (ALCdevice*)lpParameter;
186 WinMMData *pData = pDevice->ExtraData;
187 LPWAVEHDR pWaveHdr;
188 ALuint FrameSize;
189 MSG msg;
191 FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
193 SetRTPriority();
195 while(GetMessage(&msg, NULL, 0, 0))
197 if(msg.message != WOM_DONE || pData->bWaveShutdown)
198 continue;
200 pWaveHdr = ((LPWAVEHDR)msg.lParam);
202 aluMixData(pDevice, pWaveHdr->lpData, pWaveHdr->dwBufferLength/FrameSize);
204 // Send buffer back to play more data
205 waveOutWrite(pData->hWaveHandle.Out, pWaveHdr, sizeof(WAVEHDR));
206 InterlockedIncrement(&pData->lWaveBuffersCommitted);
209 // Signal Wave Thread completed event
210 if(pData->hWaveThreadEvent)
211 SetEvent(pData->hWaveThreadEvent);
213 ExitThread(0);
215 return 0;
219 WaveInProc
221 Posts a message to 'CaptureThreadProc' everytime a WaveIn Buffer is completed and
222 returns to the application (with more data)
224 static void CALLBACK WaveInProc(HWAVEIN hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2)
226 ALCdevice *pDevice = (ALCdevice*)dwInstance;
227 WinMMData *pData = pDevice->ExtraData;
229 (void)hDevice;
230 (void)dwParam2;
232 if(uMsg != WIM_DATA)
233 return;
235 // Decrement number of buffers in use
236 InterlockedDecrement(&pData->lWaveBuffersCommitted);
238 if(pData->bWaveShutdown == AL_FALSE)
240 // Notify Wave Processor Thread that a Wave Header has returned
241 PostThreadMessage(pData->ulWaveThreadID,uMsg,0,dwParam1);
243 else
245 if(pData->lWaveBuffersCommitted == 0)
247 // Post 'Quit' Message to WaveIn Processor Thread
248 PostThreadMessage(pData->ulWaveThreadID,WM_QUIT,0,0);
254 CaptureThreadProc
256 Used by "MMSYSTEM" Device. Called when a WaveIn buffer had been filled with new
257 audio data.
259 static DWORD WINAPI CaptureThreadProc(LPVOID lpParameter)
261 ALCdevice *pDevice = (ALCdevice*)lpParameter;
262 WinMMData *pData = pDevice->ExtraData;
263 LPWAVEHDR pWaveHdr;
264 ALuint FrameSize;
265 MSG msg;
267 FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType);
269 while(GetMessage(&msg, NULL, 0, 0))
271 if(msg.message != WIM_DATA || pData->bWaveShutdown)
272 continue;
274 pWaveHdr = ((LPWAVEHDR)msg.lParam);
276 WriteRingBuffer(pData->pRing, (ALubyte*)pWaveHdr->lpData,
277 pWaveHdr->dwBytesRecorded/FrameSize);
279 // Send buffer back to capture more data
280 waveInAddBuffer(pData->hWaveHandle.In,pWaveHdr,sizeof(WAVEHDR));
281 InterlockedIncrement(&pData->lWaveBuffersCommitted);
284 // Signal Wave Thread completed event
285 if(pData->hWaveThreadEvent)
286 SetEvent(pData->hWaveThreadEvent);
288 ExitThread(0);
290 return 0;
294 static ALCenum WinMMOpenPlayback(ALCdevice *pDevice, const ALCchar *deviceName)
296 WAVEFORMATEX wfexFormat;
297 WinMMData *pData = NULL;
298 UINT lDeviceID = 0;
299 MMRESULT res;
300 ALuint i = 0;
302 // Find the Device ID matching the deviceName if valid
303 if(!deviceName || strcmp(deviceName, woDefault) == 0)
304 lDeviceID = WAVE_MAPPER;
305 else
307 if(!PlaybackDeviceList)
308 ProbePlaybackDevices();
310 for(i = 0;i < NumPlaybackDevices;i++)
312 if(PlaybackDeviceList[i] &&
313 strcmp(deviceName, PlaybackDeviceList[i]) == 0)
315 lDeviceID = i;
316 break;
319 if(i == NumPlaybackDevices)
320 return ALC_INVALID_VALUE;
323 pData = calloc(1, sizeof(*pData));
324 if(!pData)
325 return ALC_OUT_OF_MEMORY;
326 pDevice->ExtraData = pData;
328 if(pDevice->FmtChans != DevFmtMono)
330 if((pDevice->Flags&DEVICE_CHANNELS_REQUEST) &&
331 pDevice->FmtChans != DevFmtStereo)
333 ERR("Failed to set %s, got Stereo instead\n", DevFmtChannelsString(pDevice->FmtChans));
334 pDevice->Flags &= ~DEVICE_CHANNELS_REQUEST;
336 pDevice->FmtChans = DevFmtStereo;
338 switch(pDevice->FmtType)
340 case DevFmtByte:
341 pDevice->FmtType = DevFmtUByte;
342 break;
343 case DevFmtUShort:
344 case DevFmtFloat:
345 pDevice->FmtType = DevFmtShort;
346 break;
347 case DevFmtUByte:
348 case DevFmtShort:
349 break;
352 memset(&wfexFormat, 0, sizeof(WAVEFORMATEX));
353 wfexFormat.wFormatTag = WAVE_FORMAT_PCM;
354 wfexFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans);
355 wfexFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8;
356 wfexFormat.nBlockAlign = wfexFormat.wBitsPerSample *
357 wfexFormat.nChannels / 8;
358 wfexFormat.nSamplesPerSec = pDevice->Frequency;
359 wfexFormat.nAvgBytesPerSec = wfexFormat.nSamplesPerSec *
360 wfexFormat.nBlockAlign;
361 wfexFormat.cbSize = 0;
363 if((res=waveOutOpen(&pData->hWaveHandle.Out, lDeviceID, &wfexFormat, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
365 ERR("waveOutOpen failed: %u\n", res);
366 goto failure;
369 pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
370 if(pData->hWaveThreadEvent == NULL)
372 ERR("CreateEvent failed: %lu\n", GetLastError());
373 goto failure;
376 pData->Frequency = pDevice->Frequency;
378 pDevice->szDeviceName = strdup((lDeviceID==WAVE_MAPPER) ? woDefault :
379 PlaybackDeviceList[lDeviceID]);
380 return ALC_NO_ERROR;
382 failure:
383 if(pData->hWaveThreadEvent)
384 CloseHandle(pData->hWaveThreadEvent);
386 if(pData->hWaveHandle.Out)
387 waveOutClose(pData->hWaveHandle.Out);
389 free(pData);
390 pDevice->ExtraData = NULL;
391 return ALC_INVALID_VALUE;
394 static void WinMMClosePlayback(ALCdevice *device)
396 WinMMData *pData = (WinMMData*)device->ExtraData;
398 // Close the Wave device
399 CloseHandle(pData->hWaveThreadEvent);
400 pData->hWaveThreadEvent = 0;
402 waveOutClose(pData->hWaveHandle.Out);
403 pData->hWaveHandle.Out = 0;
405 free(pData);
406 device->ExtraData = NULL;
409 static ALCboolean WinMMResetPlayback(ALCdevice *device)
411 WinMMData *pData = (WinMMData*)device->ExtraData;
412 ALbyte *BufferData;
413 ALint lBufferSize;
414 ALuint i;
416 pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlaybackThreadProc, (LPVOID)device, 0, &pData->ulWaveThreadID);
417 if(pData->hWaveThread == NULL)
418 return ALC_FALSE;
420 device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
421 pData->Frequency / device->Frequency);
422 if(device->Frequency != pData->Frequency)
424 if((device->Flags&DEVICE_FREQUENCY_REQUEST))
425 ERR("WinMM does not support changing sample rates (wanted %dhz, got %dhz)\n", device->Frequency, pData->Frequency);
426 device->Flags &= ~DEVICE_FREQUENCY_REQUEST;
427 device->Frequency = pData->Frequency;
430 SetDefaultWFXChannelOrder(device);
432 pData->lWaveBuffersCommitted = 0;
434 // Create 4 Buffers
435 lBufferSize = device->UpdateSize*device->NumUpdates / 4;
436 lBufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
438 BufferData = calloc(4, lBufferSize);
439 for(i = 0;i < 4;i++)
441 memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR));
442 pData->WaveBuffer[i].dwBufferLength = lBufferSize;
443 pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
444 (pData->WaveBuffer[i-1].lpData +
445 pData->WaveBuffer[i-1].dwBufferLength));
446 waveOutPrepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
447 waveOutWrite(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
448 InterlockedIncrement(&pData->lWaveBuffersCommitted);
451 return ALC_TRUE;
454 static void WinMMStopPlayback(ALCdevice *device)
456 WinMMData *pData = (WinMMData*)device->ExtraData;
457 void *buffer = NULL;
458 int i;
460 if(pData->hWaveThread == NULL)
461 return;
463 // Set flag to stop processing headers
464 pData->bWaveShutdown = AL_TRUE;
466 // Wait for signal that Wave Thread has been destroyed
467 WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE);
469 CloseHandle(pData->hWaveThread);
470 pData->hWaveThread = 0;
472 pData->bWaveShutdown = AL_FALSE;
474 // Release the wave buffers
475 for(i = 0;i < 4;i++)
477 waveOutUnprepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR));
478 if(i == 0) buffer = pData->WaveBuffer[i].lpData;
479 pData->WaveBuffer[i].lpData = NULL;
481 free(buffer);
485 static ALCenum WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName)
487 WAVEFORMATEX wfexCaptureFormat;
488 ALbyte *BufferData = NULL;
489 DWORD ulCapturedDataSize;
490 WinMMData *pData = NULL;
491 UINT lDeviceID = 0;
492 ALint lBufferSize;
493 MMRESULT res;
494 ALuint i;
496 if(!CaptureDeviceList)
497 ProbeCaptureDevices();
499 // Find the Device ID matching the deviceName if valid
500 if(deviceName)
502 for(i = 0;i < NumCaptureDevices;i++)
504 if(CaptureDeviceList[i] &&
505 strcmp(deviceName, CaptureDeviceList[i]) == 0)
507 lDeviceID = i;
508 break;
512 else
514 for(i = 0;i < NumCaptureDevices;i++)
516 if(CaptureDeviceList[i])
518 lDeviceID = i;
519 break;
523 if(i == NumCaptureDevices)
524 return ALC_INVALID_VALUE;
526 pData = calloc(1, sizeof(*pData));
527 if(!pData)
528 return ALC_OUT_OF_MEMORY;
529 pDevice->ExtraData = pData;
531 if((pDevice->FmtChans != DevFmtMono && pDevice->FmtChans != DevFmtStereo) ||
532 (pDevice->FmtType != DevFmtUByte && pDevice->FmtType != DevFmtShort))
533 goto failure;
535 memset(&wfexCaptureFormat, 0, sizeof(WAVEFORMATEX));
536 wfexCaptureFormat.wFormatTag = WAVE_FORMAT_PCM;
537 wfexCaptureFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans);
538 wfexCaptureFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8;
539 wfexCaptureFormat.nBlockAlign = wfexCaptureFormat.wBitsPerSample *
540 wfexCaptureFormat.nChannels / 8;
541 wfexCaptureFormat.nSamplesPerSec = pDevice->Frequency;
542 wfexCaptureFormat.nAvgBytesPerSec = wfexCaptureFormat.nSamplesPerSec *
543 wfexCaptureFormat.nBlockAlign;
544 wfexCaptureFormat.cbSize = 0;
546 if((res=waveInOpen(&pData->hWaveHandle.In, lDeviceID, &wfexCaptureFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
548 ERR("waveInOpen failed: %u\n", res);
549 goto failure;
552 pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
553 if(pData->hWaveThreadEvent == NULL)
555 ERR("CreateEvent failed: %lu\n", GetLastError());
556 goto failure;
559 pData->Frequency = pDevice->Frequency;
561 // Allocate circular memory buffer for the captured audio
562 ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates;
564 // Make sure circular buffer is at least 100ms in size
565 if(ulCapturedDataSize < (wfexCaptureFormat.nSamplesPerSec / 10))
566 ulCapturedDataSize = wfexCaptureFormat.nSamplesPerSec / 10;
568 pData->pRing = CreateRingBuffer(wfexCaptureFormat.nBlockAlign, ulCapturedDataSize);
569 if(!pData->pRing)
570 goto failure;
572 pData->lWaveBuffersCommitted = 0;
574 // Create 4 Buffers of 50ms each
575 lBufferSize = wfexCaptureFormat.nAvgBytesPerSec / 20;
576 lBufferSize -= (lBufferSize % wfexCaptureFormat.nBlockAlign);
578 BufferData = calloc(4, lBufferSize);
579 if(!BufferData)
580 goto failure;
582 for(i = 0;i < 4;i++)
584 memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR));
585 pData->WaveBuffer[i].dwBufferLength = lBufferSize;
586 pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
587 (pData->WaveBuffer[i-1].lpData +
588 pData->WaveBuffer[i-1].dwBufferLength));
589 pData->WaveBuffer[i].dwFlags = 0;
590 pData->WaveBuffer[i].dwLoops = 0;
591 waveInPrepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
592 waveInAddBuffer(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
593 InterlockedIncrement(&pData->lWaveBuffersCommitted);
596 pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)pDevice, 0, &pData->ulWaveThreadID);
597 if (pData->hWaveThread == NULL)
598 goto failure;
600 pDevice->szDeviceName = strdup(CaptureDeviceList[lDeviceID]);
601 return ALC_NO_ERROR;
603 failure:
604 if(pData->hWaveThread)
605 CloseHandle(pData->hWaveThread);
607 if(BufferData)
609 for(i = 0;i < 4;i++)
610 waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
611 free(BufferData);
614 if(pData->pRing)
615 DestroyRingBuffer(pData->pRing);
617 if(pData->hWaveThreadEvent)
618 CloseHandle(pData->hWaveThreadEvent);
620 if(pData->hWaveHandle.In)
621 waveInClose(pData->hWaveHandle.In);
623 free(pData);
624 pDevice->ExtraData = NULL;
625 return ALC_INVALID_VALUE;
628 static void WinMMCloseCapture(ALCdevice *pDevice)
630 WinMMData *pData = (WinMMData*)pDevice->ExtraData;
631 void *buffer = NULL;
632 int i;
634 // Call waveOutReset to shutdown wave device
635 pData->bWaveShutdown = AL_TRUE;
636 waveInReset(pData->hWaveHandle.In);
638 // Wait for signal that Wave Thread has been destroyed
639 WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE);
641 CloseHandle(pData->hWaveThread);
642 pData->hWaveThread = 0;
644 // Release the wave buffers
645 for(i = 0;i < 4;i++)
647 waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR));
648 if(i == 0) buffer = pData->WaveBuffer[i].lpData;
649 pData->WaveBuffer[i].lpData = NULL;
651 free(buffer);
653 DestroyRingBuffer(pData->pRing);
654 pData->pRing = NULL;
656 // Close the Wave device
657 CloseHandle(pData->hWaveThreadEvent);
658 pData->hWaveThreadEvent = 0;
660 waveInClose(pData->hWaveHandle.In);
661 pData->hWaveHandle.In = 0;
663 free(pData);
664 pDevice->ExtraData = NULL;
667 static void WinMMStartCapture(ALCdevice *pDevice)
669 WinMMData *pData = (WinMMData*)pDevice->ExtraData;
670 waveInStart(pData->hWaveHandle.In);
673 static void WinMMStopCapture(ALCdevice *pDevice)
675 WinMMData *pData = (WinMMData*)pDevice->ExtraData;
676 waveInStop(pData->hWaveHandle.In);
679 static ALCenum WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples)
681 WinMMData *pData = (WinMMData*)pDevice->ExtraData;
682 ReadRingBuffer(pData->pRing, pBuffer, lSamples);
683 return ALC_NO_ERROR;
686 static ALCuint WinMMAvailableSamples(ALCdevice *pDevice)
688 WinMMData *pData = (WinMMData*)pDevice->ExtraData;
689 return RingBufferSize(pData->pRing);
693 static const BackendFuncs WinMMFuncs = {
694 WinMMOpenPlayback,
695 WinMMClosePlayback,
696 WinMMResetPlayback,
697 WinMMStopPlayback,
698 WinMMOpenCapture,
699 WinMMCloseCapture,
700 WinMMStartCapture,
701 WinMMStopCapture,
702 WinMMCaptureSamples,
703 WinMMAvailableSamples
706 ALCboolean alcWinMMInit(BackendFuncs *FuncList)
708 *FuncList = WinMMFuncs;
709 return ALC_TRUE;
712 void alcWinMMDeinit()
714 ALuint lLoop;
716 for(lLoop = 0;lLoop < NumPlaybackDevices;lLoop++)
717 free(PlaybackDeviceList[lLoop]);
718 free(PlaybackDeviceList);
719 PlaybackDeviceList = NULL;
721 NumPlaybackDevices = 0;
724 for(lLoop = 0; lLoop < NumCaptureDevices; lLoop++)
725 free(CaptureDeviceList[lLoop]);
726 free(CaptureDeviceList);
727 CaptureDeviceList = NULL;
729 NumCaptureDevices = 0;
732 void alcWinMMProbe(enum DevProbe type)
734 ALuint i;
736 switch(type)
738 case DEVICE_PROBE:
739 ProbePlaybackDevices();
740 if(NumPlaybackDevices > 0)
741 AppendDeviceList(woDefault);
742 break;
744 case ALL_DEVICE_PROBE:
745 ProbePlaybackDevices();
746 if(NumPlaybackDevices > 0)
747 AppendAllDeviceList(woDefault);
748 for(i = 0;i < NumPlaybackDevices;i++)
750 if(PlaybackDeviceList[i])
751 AppendAllDeviceList(PlaybackDeviceList[i]);
753 break;
755 case CAPTURE_DEVICE_PROBE:
756 ProbeCaptureDevices();
757 for(i = 0;i < NumCaptureDevices;i++)
759 if(CaptureDeviceList[i])
760 AppendCaptureDeviceList(CaptureDeviceList[i]);
762 break;