2 * Copyright 1993 Martin Ayotte
3 * 1998-2002 Eric Pouech
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(winmm);
38 static UINT WAVE_Open(HANDLE* lphndl, UINT uDeviceID, UINT uType,
39 LPCWAVEFORMATEX lpFormat, DWORD_PTR dwCallback,
40 DWORD_PTR dwInstance, DWORD dwFlags)
47 TRACE("(%p, %d, %s, %p, %08lX, %08lX, %08X);\n",
48 lphndl, (int)uDeviceID, (uType==MMDRV_WAVEOUT)?"Out":"In", lpFormat, dwCallback,
51 if (dwFlags & WAVE_FORMAT_QUERY)
52 TRACE("WAVE_FORMAT_QUERY requested !\n");
54 dwRet = WINMM_CheckCallback(dwCallback, dwFlags, FALSE);
55 if (dwRet != MMSYSERR_NOERROR)
58 if (lpFormat == NULL) {
60 return WAVERR_BADFORMAT;
63 if ((dwFlags & WAVE_MAPPED) && (uDeviceID == (UINT)-1)) {
64 WARN("invalid parameter\n");
65 return MMSYSERR_INVALPARAM;
68 /* may have a PCMWAVEFORMAT rather than a WAVEFORMATEX so don't read cbSize */
69 TRACE("wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u\n",
70 lpFormat->wFormatTag, lpFormat->nChannels, lpFormat->nSamplesPerSec,
71 lpFormat->nAvgBytesPerSec, lpFormat->nBlockAlign, lpFormat->wBitsPerSample);
73 if ((wmld = MMDRV_Alloc(sizeof(WINE_WAVE), uType, &handle,
74 &dwFlags, &dwCallback, &dwInstance)) == NULL) {
75 return MMSYSERR_NOMEM;
79 wod.lpFormat = (LPWAVEFORMATEX)lpFormat; /* should the struct be copied iso pointer? */
80 wod.dwCallback = dwCallback;
81 wod.dwInstance = dwInstance;
84 TRACE("cb=%08lx\n", wod.dwCallback);
87 if (dwFlags & WAVE_MAPPED) {
88 wod.uMappedDeviceID = uDeviceID;
89 uDeviceID = WAVE_MAPPER;
91 wod.uMappedDeviceID = -1;
93 wmld->uDeviceID = uDeviceID;
95 dwRet = MMDRV_Open(wmld, (uType == MMDRV_WAVEOUT) ? WODM_OPEN : WIDM_OPEN,
96 (DWORD_PTR)&wod, dwFlags);
98 TRACE("dwRet = %s\n", WINMM_ErrorToString(dwRet));
99 if (dwRet != WAVERR_BADFORMAT ||
100 ((dwFlags & (WAVE_MAPPED|WAVE_FORMAT_DIRECT)) != 0) || (uDeviceID == WAVE_MAPPER)) break;
101 /* if we ask for a format which isn't supported by the physical driver,
102 * let's try to map it through the wave mapper (except, if we already tried
103 * or user didn't allow us to use acm codecs or the device is already the mapper)
105 dwFlags |= WAVE_MAPPED;
106 /* we shall loop only one */
109 if ((dwFlags & WAVE_FORMAT_QUERY) || dwRet != MMSYSERR_NOERROR) {
110 MMDRV_Free(handle, wmld);
114 if (lphndl != NULL) *lphndl = handle;
115 TRACE("=> %s hWave=%p\n", WINMM_ErrorToString(dwRet), handle);
120 /**************************************************************************
121 * waveOutGetNumDevs [WINMM.@]
123 UINT WINAPI waveOutGetNumDevs(void)
125 return MMDRV_GetNum(MMDRV_WAVEOUT);
128 /**************************************************************************
129 * waveOutGetDevCapsA [WINMM.@]
131 UINT WINAPI waveOutGetDevCapsA(UINT_PTR uDeviceID, LPWAVEOUTCAPSA lpCaps,
137 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
139 ret = waveOutGetDevCapsW(uDeviceID, &wocW, sizeof(wocW));
141 if (ret == MMSYSERR_NOERROR) {
143 wocA.wMid = wocW.wMid;
144 wocA.wPid = wocW.wPid;
145 wocA.vDriverVersion = wocW.vDriverVersion;
146 WideCharToMultiByte( CP_ACP, 0, wocW.szPname, -1, wocA.szPname,
147 sizeof(wocA.szPname), NULL, NULL );
148 wocA.dwFormats = wocW.dwFormats;
149 wocA.wChannels = wocW.wChannels;
150 wocA.dwSupport = wocW.dwSupport;
151 memcpy(lpCaps, &wocA, min(uSize, sizeof(wocA)));
156 /**************************************************************************
157 * waveOutGetDevCapsW [WINMM.@]
159 UINT WINAPI waveOutGetDevCapsW(UINT_PTR uDeviceID, LPWAVEOUTCAPSW lpCaps,
164 TRACE("(%lu %p %u)!\n", uDeviceID, lpCaps, uSize);
166 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
168 if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_WAVEOUT, TRUE)) == NULL)
169 return MMSYSERR_BADDEVICEID;
171 return MMDRV_Message(wmld, WODM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize);
174 /**************************************************************************
175 * waveOutGetErrorTextA [WINMM.@]
176 * waveInGetErrorTextA [WINMM.@]
178 UINT WINAPI waveOutGetErrorTextA(UINT uError, LPSTR lpText, UINT uSize)
182 if (lpText == NULL) ret = MMSYSERR_INVALPARAM;
183 else if (uSize == 0) ret = MMSYSERR_NOERROR;
186 LPWSTR xstr = HeapAlloc(GetProcessHeap(), 0, uSize * sizeof(WCHAR));
187 if (!xstr) ret = MMSYSERR_NOMEM;
190 ret = waveOutGetErrorTextW(uError, xstr, uSize);
191 if (ret == MMSYSERR_NOERROR)
192 WideCharToMultiByte(CP_ACP, 0, xstr, -1, lpText, uSize, NULL, NULL);
193 HeapFree(GetProcessHeap(), 0, xstr);
199 /**************************************************************************
200 * waveOutGetErrorTextW [WINMM.@]
201 * waveInGetErrorTextW [WINMM.@]
203 UINT WINAPI waveOutGetErrorTextW(UINT uError, LPWSTR lpText, UINT uSize)
205 UINT ret = MMSYSERR_BADERRNUM;
207 if (lpText == NULL) ret = MMSYSERR_INVALPARAM;
208 else if (uSize == 0) ret = MMSYSERR_NOERROR;
210 /* test has been removed because MMSYSERR_BASE is 0, and gcc did emit
211 * a warning for the test was always true */
212 (/*uError >= MMSYSERR_BASE && */ uError <= MMSYSERR_LASTERROR) ||
213 (uError >= WAVERR_BASE && uError <= WAVERR_LASTERROR)) {
214 if (LoadStringW(hWinMM32Instance,
215 uError, lpText, uSize) > 0) {
216 ret = MMSYSERR_NOERROR;
222 /**************************************************************************
223 * waveOutOpen [WINMM.@]
224 * All the args/structs have the same layout as the win16 equivalents
226 MMRESULT WINAPI waveOutOpen(LPHWAVEOUT lphWaveOut, UINT uDeviceID,
227 LPCWAVEFORMATEX lpFormat, DWORD_PTR dwCallback,
228 DWORD_PTR dwInstance, DWORD dwFlags)
230 return WAVE_Open((HANDLE*)lphWaveOut, uDeviceID, MMDRV_WAVEOUT, lpFormat,
231 dwCallback, dwInstance, dwFlags);
234 /**************************************************************************
235 * waveOutClose [WINMM.@]
237 UINT WINAPI waveOutClose(HWAVEOUT hWaveOut)
242 TRACE("(%p)\n", hWaveOut);
244 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
245 return MMSYSERR_INVALHANDLE;
247 dwRet = MMDRV_Close(wmld, WODM_CLOSE);
248 if (dwRet != WAVERR_STILLPLAYING)
249 MMDRV_Free(hWaveOut, wmld);
254 /**************************************************************************
255 * waveOutPrepareHeader [WINMM.@]
257 UINT WINAPI waveOutPrepareHeader(HWAVEOUT hWaveOut,
258 WAVEHDR* lpWaveOutHdr, UINT uSize)
263 TRACE("(%p, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
265 if (lpWaveOutHdr == NULL || uSize < sizeof (WAVEHDR))
266 return MMSYSERR_INVALPARAM;
268 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
269 return MMSYSERR_INVALHANDLE;
271 if ((result = MMDRV_Message(wmld, WODM_PREPARE, (DWORD_PTR)lpWaveOutHdr,
272 uSize)) != MMSYSERR_NOTSUPPORTED)
275 if (lpWaveOutHdr->dwFlags & WHDR_INQUEUE)
276 return WAVERR_STILLPLAYING;
278 lpWaveOutHdr->dwFlags |= WHDR_PREPARED;
279 lpWaveOutHdr->dwFlags &= ~WHDR_DONE;
281 return MMSYSERR_NOERROR;
284 /**************************************************************************
285 * waveOutUnprepareHeader [WINMM.@]
287 UINT WINAPI waveOutUnprepareHeader(HWAVEOUT hWaveOut,
288 LPWAVEHDR lpWaveOutHdr, UINT uSize)
293 TRACE("(%p, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
295 if (lpWaveOutHdr == NULL || uSize < sizeof (WAVEHDR))
296 return MMSYSERR_INVALPARAM;
298 if (!(lpWaveOutHdr->dwFlags & WHDR_PREPARED)) {
299 return MMSYSERR_NOERROR;
302 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
303 return MMSYSERR_INVALHANDLE;
305 if ((result = MMDRV_Message(wmld, WODM_UNPREPARE, (DWORD_PTR)lpWaveOutHdr,
306 uSize)) != MMSYSERR_NOTSUPPORTED)
309 if (lpWaveOutHdr->dwFlags & WHDR_INQUEUE)
310 return WAVERR_STILLPLAYING;
312 lpWaveOutHdr->dwFlags &= ~WHDR_PREPARED;
313 lpWaveOutHdr->dwFlags |= WHDR_DONE;
315 return MMSYSERR_NOERROR;
318 /**************************************************************************
319 * waveOutWrite [WINMM.@]
321 UINT WINAPI waveOutWrite(HWAVEOUT hWaveOut, LPWAVEHDR lpWaveOutHdr,
326 TRACE("(%p, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
328 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
329 return MMSYSERR_INVALHANDLE;
331 return MMDRV_Message(wmld, WODM_WRITE, (DWORD_PTR)lpWaveOutHdr, uSize);
334 /**************************************************************************
335 * waveOutBreakLoop [WINMM.@]
337 UINT WINAPI waveOutBreakLoop(HWAVEOUT hWaveOut)
341 TRACE("(%p);\n", hWaveOut);
343 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
344 return MMSYSERR_INVALHANDLE;
345 return MMDRV_Message(wmld, WODM_BREAKLOOP, 0L, 0L);
348 /**************************************************************************
349 * waveOutPause [WINMM.@]
351 UINT WINAPI waveOutPause(HWAVEOUT hWaveOut)
355 TRACE("(%p);\n", hWaveOut);
357 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
358 return MMSYSERR_INVALHANDLE;
359 return MMDRV_Message(wmld, WODM_PAUSE, 0L, 0L);
362 /**************************************************************************
363 * waveOutReset [WINMM.@]
365 UINT WINAPI waveOutReset(HWAVEOUT hWaveOut)
369 TRACE("(%p);\n", hWaveOut);
371 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
372 return MMSYSERR_INVALHANDLE;
373 return MMDRV_Message(wmld, WODM_RESET, 0L, 0L);
376 /**************************************************************************
377 * waveOutRestart [WINMM.@]
379 UINT WINAPI waveOutRestart(HWAVEOUT hWaveOut)
383 TRACE("(%p);\n", hWaveOut);
385 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
386 return MMSYSERR_INVALHANDLE;
387 return MMDRV_Message(wmld, WODM_RESTART, 0L, 0L);
390 /**************************************************************************
391 * waveOutGetPosition [WINMM.@]
393 UINT WINAPI waveOutGetPosition(HWAVEOUT hWaveOut, LPMMTIME lpTime,
398 TRACE("(%p, %p, %u);\n", hWaveOut, lpTime, uSize);
400 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
401 return MMSYSERR_INVALHANDLE;
403 return MMDRV_Message(wmld, WODM_GETPOS, (DWORD_PTR)lpTime, uSize);
406 /**************************************************************************
407 * waveOutGetPitch [WINMM.@]
409 UINT WINAPI waveOutGetPitch(HWAVEOUT hWaveOut, LPDWORD lpdw)
413 TRACE("(%p, %p);\n", hWaveOut, lpdw);
415 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
416 return MMSYSERR_INVALHANDLE;
417 return MMDRV_Message(wmld, WODM_GETPITCH, (DWORD_PTR)lpdw, 0L);
420 /**************************************************************************
421 * waveOutSetPitch [WINMM.@]
423 UINT WINAPI waveOutSetPitch(HWAVEOUT hWaveOut, DWORD dw)
427 TRACE("(%p, %08x);\n", hWaveOut, dw);
429 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
430 return MMSYSERR_INVALHANDLE;
431 return MMDRV_Message(wmld, WODM_SETPITCH, dw, 0L);
434 /**************************************************************************
435 * waveOutGetPlaybackRate [WINMM.@]
437 UINT WINAPI waveOutGetPlaybackRate(HWAVEOUT hWaveOut, LPDWORD lpdw)
441 TRACE("(%p, %p);\n", hWaveOut, lpdw);
443 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
444 return MMSYSERR_INVALHANDLE;
445 return MMDRV_Message(wmld, WODM_GETPLAYBACKRATE, (DWORD_PTR)lpdw, 0L);
448 /**************************************************************************
449 * waveOutSetPlaybackRate [WINMM.@]
451 UINT WINAPI waveOutSetPlaybackRate(HWAVEOUT hWaveOut, DWORD dw)
455 TRACE("(%p, %08x);\n", hWaveOut, dw);
457 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
458 return MMSYSERR_INVALHANDLE;
459 return MMDRV_Message(wmld, WODM_SETPLAYBACKRATE, dw, 0L);
462 /**************************************************************************
463 * waveOutGetVolume [WINMM.@]
465 UINT WINAPI waveOutGetVolume(HWAVEOUT hWaveOut, LPDWORD lpdw)
469 TRACE("(%p, %p);\n", hWaveOut, lpdw);
472 WARN("invalid parameter\n");
473 return MMSYSERR_INVALPARAM;
476 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, TRUE)) == NULL)
477 return MMSYSERR_INVALHANDLE;
479 return MMDRV_Message(wmld, WODM_GETVOLUME, (DWORD_PTR)lpdw, 0L);
482 /**************************************************************************
483 * waveOutSetVolume [WINMM.@]
485 UINT WINAPI waveOutSetVolume(HWAVEOUT hWaveOut, DWORD dw)
489 TRACE("(%p, %08x);\n", hWaveOut, dw);
491 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, TRUE)) == NULL)
492 return MMSYSERR_INVALHANDLE;
494 return MMDRV_Message(wmld, WODM_SETVOLUME, dw, 0L);
497 /**************************************************************************
498 * waveOutGetID [WINMM.@]
500 UINT WINAPI waveOutGetID(HWAVEOUT hWaveOut, UINT* lpuDeviceID)
504 TRACE("(%p, %p);\n", hWaveOut, lpuDeviceID);
506 if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
508 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL)
509 return MMSYSERR_INVALHANDLE;
511 *lpuDeviceID = wmld->uDeviceID;
515 /**************************************************************************
516 * waveOutMessage [WINMM.@]
518 UINT WINAPI waveOutMessage(HWAVEOUT hWaveOut, UINT uMessage,
519 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
523 TRACE("(%p, %u, %ld, %ld)\n", hWaveOut, uMessage, dwParam1, dwParam2);
525 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, FALSE)) == NULL) {
526 if ((wmld = MMDRV_Get(hWaveOut, MMDRV_WAVEOUT, TRUE)) != NULL) {
527 return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
529 WARN("invalid handle\n");
530 return MMSYSERR_INVALHANDLE;
534 if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER)) {
535 WARN("invalid parameter\n");
536 return MMSYSERR_INVALPARAM;
539 return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2);
542 /**************************************************************************
543 * waveInGetNumDevs [WINMM.@]
545 UINT WINAPI waveInGetNumDevs(void)
547 return MMDRV_GetNum(MMDRV_WAVEIN);
550 /**************************************************************************
551 * waveInGetDevCapsW [WINMM.@]
553 UINT WINAPI waveInGetDevCapsW(UINT_PTR uDeviceID, LPWAVEINCAPSW lpCaps, UINT uSize)
557 TRACE("(%lu %p %u)!\n", uDeviceID, lpCaps, uSize);
559 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
561 if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_WAVEIN, TRUE)) == NULL)
562 return MMSYSERR_BADDEVICEID;
564 return MMDRV_Message(wmld, WIDM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize);
567 /**************************************************************************
568 * waveInGetDevCapsA [WINMM.@]
570 UINT WINAPI waveInGetDevCapsA(UINT_PTR uDeviceID, LPWAVEINCAPSA lpCaps, UINT uSize)
575 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
577 ret = waveInGetDevCapsW(uDeviceID, &wicW, sizeof(wicW));
579 if (ret == MMSYSERR_NOERROR) {
581 wicA.wMid = wicW.wMid;
582 wicA.wPid = wicW.wPid;
583 wicA.vDriverVersion = wicW.vDriverVersion;
584 WideCharToMultiByte( CP_ACP, 0, wicW.szPname, -1, wicA.szPname,
585 sizeof(wicA.szPname), NULL, NULL );
586 wicA.dwFormats = wicW.dwFormats;
587 wicA.wChannels = wicW.wChannels;
588 memcpy(lpCaps, &wicA, min(uSize, sizeof(wicA)));
593 /**************************************************************************
594 * waveInOpen [WINMM.@]
596 MMRESULT WINAPI waveInOpen(HWAVEIN* lphWaveIn, UINT uDeviceID,
597 LPCWAVEFORMATEX lpFormat, DWORD_PTR dwCallback,
598 DWORD_PTR dwInstance, DWORD dwFlags)
600 return WAVE_Open((HANDLE*)lphWaveIn, uDeviceID, MMDRV_WAVEIN, lpFormat,
601 dwCallback, dwInstance, dwFlags);
604 /**************************************************************************
605 * waveInClose [WINMM.@]
607 UINT WINAPI waveInClose(HWAVEIN hWaveIn)
612 TRACE("(%p)\n", hWaveIn);
614 if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL)
615 return MMSYSERR_INVALHANDLE;
617 dwRet = MMDRV_Message(wmld, WIDM_CLOSE, 0L, 0L);
618 if (dwRet != WAVERR_STILLPLAYING)
619 MMDRV_Free(hWaveIn, wmld);
623 /**************************************************************************
624 * waveInPrepareHeader [WINMM.@]
626 UINT WINAPI waveInPrepareHeader(HWAVEIN hWaveIn, WAVEHDR* lpWaveInHdr,
632 TRACE("(%p, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
634 if (lpWaveInHdr == NULL || uSize < sizeof (WAVEHDR))
635 return MMSYSERR_INVALPARAM;
637 if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL)
638 return MMSYSERR_INVALHANDLE;
640 if ((result = MMDRV_Message(wmld, WIDM_PREPARE, (DWORD_PTR)lpWaveInHdr,
641 uSize)) != MMSYSERR_NOTSUPPORTED)
644 if (lpWaveInHdr->dwFlags & WHDR_INQUEUE)
645 return WAVERR_STILLPLAYING;
647 lpWaveInHdr->dwFlags |= WHDR_PREPARED;
648 lpWaveInHdr->dwFlags &= ~WHDR_DONE;
649 lpWaveInHdr->dwBytesRecorded = 0;
651 return MMSYSERR_NOERROR;
654 /**************************************************************************
655 * waveInUnprepareHeader [WINMM.@]
657 UINT WINAPI waveInUnprepareHeader(HWAVEIN hWaveIn, WAVEHDR* lpWaveInHdr,
663 TRACE("(%p, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
665 if (lpWaveInHdr == NULL || uSize < sizeof (WAVEHDR))
666 return MMSYSERR_INVALPARAM;
668 if (!(lpWaveInHdr->dwFlags & WHDR_PREPARED))
669 return MMSYSERR_NOERROR;
671 if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL)
672 return MMSYSERR_INVALHANDLE;
674 if ((result = MMDRV_Message(wmld, WIDM_UNPREPARE, (DWORD_PTR)lpWaveInHdr,
675 uSize)) != MMSYSERR_NOTSUPPORTED)
678 if (lpWaveInHdr->dwFlags & WHDR_INQUEUE)
679 return WAVERR_STILLPLAYING;
681 lpWaveInHdr->dwFlags &= ~WHDR_PREPARED;
682 lpWaveInHdr->dwFlags |= WHDR_DONE;
684 return MMSYSERR_NOERROR;
687 /**************************************************************************
688 * waveInAddBuffer [WINMM.@]
690 UINT WINAPI waveInAddBuffer(HWAVEIN hWaveIn,
691 WAVEHDR* lpWaveInHdr, UINT uSize)
695 TRACE("(%p, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
697 if (lpWaveInHdr == NULL) return MMSYSERR_INVALPARAM;
698 if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL)
699 return MMSYSERR_INVALHANDLE;
701 return MMDRV_Message(wmld, WIDM_ADDBUFFER, (DWORD_PTR)lpWaveInHdr, uSize);
704 /**************************************************************************
705 * waveInReset [WINMM.@]
707 UINT WINAPI waveInReset(HWAVEIN hWaveIn)
711 TRACE("(%p);\n", hWaveIn);
713 if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL)
714 return MMSYSERR_INVALHANDLE;
716 return MMDRV_Message(wmld, WIDM_RESET, 0L, 0L);
719 /**************************************************************************
720 * waveInStart [WINMM.@]
722 UINT WINAPI waveInStart(HWAVEIN hWaveIn)
726 TRACE("(%p);\n", hWaveIn);
728 if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL)
729 return MMSYSERR_INVALHANDLE;
731 return MMDRV_Message(wmld, WIDM_START, 0L, 0L);
734 /**************************************************************************
735 * waveInStop [WINMM.@]
737 UINT WINAPI waveInStop(HWAVEIN hWaveIn)
741 TRACE("(%p);\n", hWaveIn);
743 if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL)
744 return MMSYSERR_INVALHANDLE;
746 return MMDRV_Message(wmld,WIDM_STOP, 0L, 0L);
749 /**************************************************************************
750 * waveInGetPosition [WINMM.@]
752 UINT WINAPI waveInGetPosition(HWAVEIN hWaveIn, LPMMTIME lpTime,
757 TRACE("(%p, %p, %u);\n", hWaveIn, lpTime, uSize);
759 if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL)
760 return MMSYSERR_INVALHANDLE;
762 return MMDRV_Message(wmld, WIDM_GETPOS, (DWORD_PTR)lpTime, uSize);
765 /**************************************************************************
766 * waveInGetID [WINMM.@]
768 UINT WINAPI waveInGetID(HWAVEIN hWaveIn, UINT* lpuDeviceID)
772 TRACE("(%p, %p);\n", hWaveIn, lpuDeviceID);
774 if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
776 if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL)
777 return MMSYSERR_INVALHANDLE;
779 *lpuDeviceID = wmld->uDeviceID;
780 return MMSYSERR_NOERROR;
783 /**************************************************************************
784 * waveInMessage [WINMM.@]
786 UINT WINAPI waveInMessage(HWAVEIN hWaveIn, UINT uMessage,
787 DWORD_PTR dwParam1, DWORD_PTR dwParam2)
791 TRACE("(%p, %u, %ld, %ld)\n", hWaveIn, uMessage, dwParam1, dwParam2);
793 if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, FALSE)) == NULL) {
794 if ((wmld = MMDRV_Get(hWaveIn, MMDRV_WAVEIN, TRUE)) != NULL) {
795 return MMDRV_PhysicalFeatures(wmld, uMessage, dwParam1, dwParam2);
797 return MMSYSERR_INVALHANDLE;
801 if (uMessage < DRVM_IOCTL || (uMessage >= DRVM_IOCTL_LAST && uMessage < DRVM_MAPPER))
802 return MMSYSERR_INVALPARAM;
805 return MMDRV_Message(wmld, uMessage, dwParam1, dwParam2);
808 /**************************************************************************
809 * find out the real mixer ID depending on hmix (depends on dwFlags)
811 static UINT MIXER_GetDev(HMIXEROBJ hmix, DWORD dwFlags, LPWINE_MIXER * lplpwm)
813 LPWINE_MIXER lpwm = NULL;
814 UINT uRet = MMSYSERR_NOERROR;
816 switch (dwFlags & 0xF0000000ul) {
817 case MIXER_OBJECTF_MIXER:
818 lpwm = (LPWINE_MIXER)MMDRV_Get(hmix, MMDRV_MIXER, TRUE);
820 case MIXER_OBJECTF_HMIXER:
821 lpwm = (LPWINE_MIXER)MMDRV_Get(hmix, MMDRV_MIXER, FALSE);
823 case MIXER_OBJECTF_WAVEOUT:
824 lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_WAVEOUT, TRUE, MMDRV_MIXER);
826 case MIXER_OBJECTF_HWAVEOUT:
827 lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_WAVEOUT, FALSE, MMDRV_MIXER);
829 case MIXER_OBJECTF_WAVEIN:
830 lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_WAVEIN, TRUE, MMDRV_MIXER);
832 case MIXER_OBJECTF_HWAVEIN:
833 lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_WAVEIN, FALSE, MMDRV_MIXER);
835 case MIXER_OBJECTF_MIDIOUT:
836 lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_MIDIOUT, TRUE, MMDRV_MIXER);
838 case MIXER_OBJECTF_HMIDIOUT:
839 lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_MIDIOUT, FALSE, MMDRV_MIXER);
841 case MIXER_OBJECTF_MIDIIN:
842 lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_MIDIIN, TRUE, MMDRV_MIXER);
844 case MIXER_OBJECTF_HMIDIIN:
845 lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_MIDIIN, FALSE, MMDRV_MIXER);
847 case MIXER_OBJECTF_AUX:
848 lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_AUX, TRUE, MMDRV_MIXER);
851 WARN("Unsupported flag (%08lx)\n", dwFlags & 0xF0000000ul);
853 uRet = MMSYSERR_INVALFLAG;
857 if (lpwm == 0 && uRet == MMSYSERR_NOERROR)
858 uRet = MMSYSERR_INVALPARAM;
862 /**************************************************************************
863 * mixerGetNumDevs [WINMM.@]
865 UINT WINAPI mixerGetNumDevs(void)
867 return MMDRV_GetNum(MMDRV_MIXER);
870 /**************************************************************************
871 * mixerGetDevCapsA [WINMM.@]
873 UINT WINAPI mixerGetDevCapsA(UINT_PTR uDeviceID, LPMIXERCAPSA lpCaps, UINT uSize)
878 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
880 ret = mixerGetDevCapsW(uDeviceID, &micW, sizeof(micW));
882 if (ret == MMSYSERR_NOERROR) {
884 micA.wMid = micW.wMid;
885 micA.wPid = micW.wPid;
886 micA.vDriverVersion = micW.vDriverVersion;
887 WideCharToMultiByte( CP_ACP, 0, micW.szPname, -1, micA.szPname,
888 sizeof(micA.szPname), NULL, NULL );
889 micA.fdwSupport = micW.fdwSupport;
890 micA.cDestinations = micW.cDestinations;
891 memcpy(lpCaps, &micA, min(uSize, sizeof(micA)));
896 /**************************************************************************
897 * mixerGetDevCapsW [WINMM.@]
899 UINT WINAPI mixerGetDevCapsW(UINT_PTR uDeviceID, LPMIXERCAPSW lpCaps, UINT uSize)
903 if (lpCaps == NULL) return MMSYSERR_INVALPARAM;
905 if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_MIXER, TRUE)) == NULL)
906 return MMSYSERR_BADDEVICEID;
908 return MMDRV_Message(wmld, MXDM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize);
911 static void CALLBACK MIXER_WCallback(HMIXEROBJ hmx, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam, DWORD_PTR param2)
913 HWND hWnd = (HWND)dwInstance;
918 PostMessageW(hWnd, uMsg, (WPARAM)hmx, (LPARAM)dwParam);
921 /**************************************************************************
922 * mixerOpen [WINMM.@]
924 UINT WINAPI mixerOpen(LPHMIXER lphMix, UINT uDeviceID, DWORD_PTR dwCallback,
925 DWORD_PTR dwInstance, DWORD fdwOpen)
932 TRACE("(%p, %d, %08lx, %08lx, %08x)\n",
933 lphMix, uDeviceID, dwCallback, dwInstance, fdwOpen);
935 dwRet = WINMM_CheckCallback(dwCallback, fdwOpen, TRUE);
936 if (dwRet != MMSYSERR_NOERROR)
939 mod.dwCallback = (DWORD_PTR)MIXER_WCallback;
940 if ((fdwOpen & CALLBACK_TYPEMASK) == CALLBACK_WINDOW)
941 mod.dwInstance = dwCallback;
945 /* We're remapping to CALLBACK_FUNCTION because that's what old winmm is
946 * documented to do when opening the mixer driver.
947 * FIXME: Native supports CALLBACK_EVENT + CALLBACK_THREAD flags since w2k.
948 * FIXME: The non ALSA drivers ignore callback requests - bug.
951 wmld = MMDRV_Alloc(sizeof(WINE_MIXER), MMDRV_MIXER, &hMix, &fdwOpen,
952 &dwCallback, &dwInstance);
953 wmld->uDeviceID = uDeviceID;
956 dwRet = MMDRV_Open(wmld, MXDM_OPEN, (DWORD_PTR)&mod, CALLBACK_FUNCTION);
958 if (dwRet != MMSYSERR_NOERROR) {
959 MMDRV_Free(hMix, wmld);
962 if (lphMix) *lphMix = hMix;
963 TRACE("=> %d hMixer=%p\n", dwRet, hMix);
968 /**************************************************************************
969 * mixerClose [WINMM.@]
971 UINT WINAPI mixerClose(HMIXER hMix)
976 TRACE("(%p)\n", hMix);
978 if ((wmld = MMDRV_Get(hMix, MMDRV_MIXER, FALSE)) == NULL) return MMSYSERR_INVALHANDLE;
980 dwRet = MMDRV_Close(wmld, MXDM_CLOSE);
981 MMDRV_Free(hMix, wmld);
986 /**************************************************************************
987 * mixerGetID [WINMM.@]
989 UINT WINAPI mixerGetID(HMIXEROBJ hmix, LPUINT lpid, DWORD fdwID)
992 UINT uRet = MMSYSERR_NOERROR;
994 TRACE("(%p %p %08x)\n", hmix, lpid, fdwID);
996 if ((uRet = MIXER_GetDev(hmix, fdwID, &lpwm)) != MMSYSERR_NOERROR)
1000 *lpid = lpwm->mld.uDeviceID;
1005 /**************************************************************************
1006 * mixerGetControlDetailsW [WINMM.@]
1008 UINT WINAPI mixerGetControlDetailsW(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcdW,
1012 UINT uRet = MMSYSERR_NOERROR;
1014 TRACE("(%p, %p, %08x)\n", hmix, lpmcdW, fdwDetails);
1016 if ((uRet = MIXER_GetDev(hmix, fdwDetails, &lpwm)) != MMSYSERR_NOERROR)
1019 if (lpmcdW == NULL || lpmcdW->cbStruct != sizeof(*lpmcdW))
1020 return MMSYSERR_INVALPARAM;
1022 return MMDRV_Message(&lpwm->mld, MXDM_GETCONTROLDETAILS, (DWORD_PTR)lpmcdW,
1026 /**************************************************************************
1027 * mixerGetControlDetailsA [WINMM.@]
1029 UINT WINAPI mixerGetControlDetailsA(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcdA,
1032 DWORD ret = MMSYSERR_NOTENABLED;
1034 TRACE("(%p, %p, %08x)\n", hmix, lpmcdA, fdwDetails);
1036 if (lpmcdA == NULL || lpmcdA->cbStruct != sizeof(*lpmcdA))
1037 return MMSYSERR_INVALPARAM;
1039 switch (fdwDetails & MIXER_GETCONTROLDETAILSF_QUERYMASK) {
1040 case MIXER_GETCONTROLDETAILSF_VALUE:
1041 /* can safely use A structure as it is, no string inside */
1042 ret = mixerGetControlDetailsW(hmix, lpmcdA, fdwDetails);
1044 case MIXER_GETCONTROLDETAILSF_LISTTEXT:
1046 MIXERCONTROLDETAILS_LISTTEXTA *pDetailsA = lpmcdA->paDetails;
1047 MIXERCONTROLDETAILS_LISTTEXTW *pDetailsW;
1048 int size = max(1, lpmcdA->cChannels) * sizeof(MIXERCONTROLDETAILS_LISTTEXTW);
1051 if (lpmcdA->u.cMultipleItems != 0) {
1052 size *= lpmcdA->u.cMultipleItems;
1054 pDetailsW = HeapAlloc(GetProcessHeap(), 0, size);
1055 lpmcdA->paDetails = pDetailsW;
1056 lpmcdA->cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXTW);
1057 /* set up lpmcd->paDetails */
1058 ret = mixerGetControlDetailsW(hmix, lpmcdA, fdwDetails);
1059 /* copy from lpmcd->paDetails back to paDetailsW; */
1060 if (ret == MMSYSERR_NOERROR) {
1061 for (i = 0; i < lpmcdA->u.cMultipleItems * lpmcdA->cChannels; i++) {
1062 pDetailsA->dwParam1 = pDetailsW->dwParam1;
1063 pDetailsA->dwParam2 = pDetailsW->dwParam2;
1064 WideCharToMultiByte( CP_ACP, 0, pDetailsW->szName, -1,
1066 sizeof(pDetailsA->szName), NULL, NULL );
1070 pDetailsA -= lpmcdA->u.cMultipleItems * lpmcdA->cChannels;
1071 pDetailsW -= lpmcdA->u.cMultipleItems * lpmcdA->cChannels;
1073 HeapFree(GetProcessHeap(), 0, pDetailsW);
1074 lpmcdA->paDetails = pDetailsA;
1075 lpmcdA->cbDetails = sizeof(MIXERCONTROLDETAILS_LISTTEXTA);
1079 ERR("Unsupported fdwDetails=0x%08x\n", fdwDetails);
1085 /**************************************************************************
1086 * mixerGetLineControlsA [WINMM.@]
1088 UINT WINAPI mixerGetLineControlsA(HMIXEROBJ hmix, LPMIXERLINECONTROLSA lpmlcA,
1091 MIXERLINECONTROLSW mlcW;
1095 TRACE("(%p, %p, %08x)\n", hmix, lpmlcA, fdwControls);
1097 if (lpmlcA == NULL || lpmlcA->cbStruct != sizeof(*lpmlcA) ||
1098 lpmlcA->cbmxctrl != sizeof(MIXERCONTROLA))
1099 return MMSYSERR_INVALPARAM;
1101 mlcW.cbStruct = sizeof(mlcW);
1102 mlcW.dwLineID = lpmlcA->dwLineID;
1103 mlcW.u.dwControlID = lpmlcA->u.dwControlID;
1104 mlcW.u.dwControlType = lpmlcA->u.dwControlType;
1106 /* Debugging on Windows shows for MIXER_GETLINECONTROLSF_ONEBYTYPE only,
1107 the control count is assumed to be 1 - This is relied upon by a game,
1108 "Dynomite Deluze" */
1109 if (MIXER_GETLINECONTROLSF_ONEBYTYPE == (fdwControls & MIXER_GETLINECONTROLSF_QUERYMASK)) {
1112 mlcW.cControls = lpmlcA->cControls;
1114 mlcW.cbmxctrl = sizeof(MIXERCONTROLW);
1115 mlcW.pamxctrl = HeapAlloc(GetProcessHeap(), 0,
1116 mlcW.cControls * mlcW.cbmxctrl);
1118 ret = mixerGetLineControlsW(hmix, &mlcW, fdwControls);
1120 if (ret == MMSYSERR_NOERROR) {
1121 lpmlcA->dwLineID = mlcW.dwLineID;
1122 lpmlcA->u.dwControlID = mlcW.u.dwControlID;
1123 lpmlcA->u.dwControlType = mlcW.u.dwControlType;
1125 for (i = 0; i < mlcW.cControls; i++) {
1126 lpmlcA->pamxctrl[i].cbStruct = sizeof(MIXERCONTROLA);
1127 lpmlcA->pamxctrl[i].dwControlID = mlcW.pamxctrl[i].dwControlID;
1128 lpmlcA->pamxctrl[i].dwControlType = mlcW.pamxctrl[i].dwControlType;
1129 lpmlcA->pamxctrl[i].fdwControl = mlcW.pamxctrl[i].fdwControl;
1130 lpmlcA->pamxctrl[i].cMultipleItems = mlcW.pamxctrl[i].cMultipleItems;
1131 WideCharToMultiByte( CP_ACP, 0, mlcW.pamxctrl[i].szShortName, -1,
1132 lpmlcA->pamxctrl[i].szShortName,
1133 sizeof(lpmlcA->pamxctrl[i].szShortName), NULL, NULL );
1134 WideCharToMultiByte( CP_ACP, 0, mlcW.pamxctrl[i].szName, -1,
1135 lpmlcA->pamxctrl[i].szName,
1136 sizeof(lpmlcA->pamxctrl[i].szName), NULL, NULL );
1137 /* sizeof(lpmlcA->pamxctrl[i].Bounds) ==
1138 * sizeof(mlcW.pamxctrl[i].Bounds) */
1139 memcpy(&lpmlcA->pamxctrl[i].Bounds, &mlcW.pamxctrl[i].Bounds,
1140 sizeof(mlcW.pamxctrl[i].Bounds));
1141 /* sizeof(lpmlcA->pamxctrl[i].Metrics) ==
1142 * sizeof(mlcW.pamxctrl[i].Metrics) */
1143 memcpy(&lpmlcA->pamxctrl[i].Metrics, &mlcW.pamxctrl[i].Metrics,
1144 sizeof(mlcW.pamxctrl[i].Metrics));
1148 HeapFree(GetProcessHeap(), 0, mlcW.pamxctrl);
1153 /**************************************************************************
1154 * mixerGetLineControlsW [WINMM.@]
1156 UINT WINAPI mixerGetLineControlsW(HMIXEROBJ hmix, LPMIXERLINECONTROLSW lpmlcW,
1160 UINT uRet = MMSYSERR_NOERROR;
1162 TRACE("(%p, %p, %08x)\n", hmix, lpmlcW, fdwControls);
1164 if ((uRet = MIXER_GetDev(hmix, fdwControls, &lpwm)) != MMSYSERR_NOERROR)
1167 if (lpmlcW == NULL || lpmlcW->cbStruct != sizeof(*lpmlcW))
1168 return MMSYSERR_INVALPARAM;
1170 return MMDRV_Message(&lpwm->mld, MXDM_GETLINECONTROLS, (DWORD_PTR)lpmlcW,
1174 /**************************************************************************
1175 * mixerGetLineInfoW [WINMM.@]
1177 UINT WINAPI mixerGetLineInfoW(HMIXEROBJ hmix, LPMIXERLINEW lpmliW, DWORD fdwInfo)
1180 UINT uRet = MMSYSERR_NOERROR;
1182 TRACE("(%p, %p, %08x)\n", hmix, lpmliW, fdwInfo);
1184 if ((uRet = MIXER_GetDev(hmix, fdwInfo, &lpwm)) != MMSYSERR_NOERROR)
1187 return MMDRV_Message(&lpwm->mld, MXDM_GETLINEINFO, (DWORD_PTR)lpmliW,
1191 /**************************************************************************
1192 * mixerGetLineInfoA [WINMM.@]
1194 UINT WINAPI mixerGetLineInfoA(HMIXEROBJ hmix, LPMIXERLINEA lpmliA,
1200 TRACE("(%p, %p, %08x)\n", hmix, lpmliA, fdwInfo);
1202 if (lpmliA == NULL || lpmliA->cbStruct != sizeof(*lpmliA))
1203 return MMSYSERR_INVALPARAM;
1205 mliW.cbStruct = sizeof(mliW);
1206 switch (fdwInfo & MIXER_GETLINEINFOF_QUERYMASK) {
1207 case MIXER_GETLINEINFOF_COMPONENTTYPE:
1208 mliW.dwComponentType = lpmliA->dwComponentType;
1210 case MIXER_GETLINEINFOF_DESTINATION:
1211 mliW.dwDestination = lpmliA->dwDestination;
1213 case MIXER_GETLINEINFOF_LINEID:
1214 mliW.dwLineID = lpmliA->dwLineID;
1216 case MIXER_GETLINEINFOF_SOURCE:
1217 mliW.dwDestination = lpmliA->dwDestination;
1218 mliW.dwSource = lpmliA->dwSource;
1220 case MIXER_GETLINEINFOF_TARGETTYPE:
1221 mliW.Target.dwType = lpmliA->Target.dwType;
1222 mliW.Target.wMid = lpmliA->Target.wMid;
1223 mliW.Target.wPid = lpmliA->Target.wPid;
1224 mliW.Target.vDriverVersion = lpmliA->Target.vDriverVersion;
1225 MultiByteToWideChar( CP_ACP, 0, lpmliA->Target.szPname, -1, mliW.Target.szPname, sizeof(mliW.Target.szPname)/sizeof(WCHAR));
1228 WARN("Unsupported fdwControls=0x%08x\n", fdwInfo);
1229 return MMSYSERR_INVALFLAG;
1232 ret = mixerGetLineInfoW(hmix, &mliW, fdwInfo);
1234 if(ret == MMSYSERR_NOERROR)
1236 lpmliA->dwDestination = mliW.dwDestination;
1237 lpmliA->dwSource = mliW.dwSource;
1238 lpmliA->dwLineID = mliW.dwLineID;
1239 lpmliA->fdwLine = mliW.fdwLine;
1240 lpmliA->dwUser = mliW.dwUser;
1241 lpmliA->dwComponentType = mliW.dwComponentType;
1242 lpmliA->cChannels = mliW.cChannels;
1243 lpmliA->cConnections = mliW.cConnections;
1244 lpmliA->cControls = mliW.cControls;
1245 WideCharToMultiByte( CP_ACP, 0, mliW.szShortName, -1, lpmliA->szShortName,
1246 sizeof(lpmliA->szShortName), NULL, NULL);
1247 WideCharToMultiByte( CP_ACP, 0, mliW.szName, -1, lpmliA->szName,
1248 sizeof(lpmliA->szName), NULL, NULL );
1249 lpmliA->Target.dwType = mliW.Target.dwType;
1250 lpmliA->Target.dwDeviceID = mliW.Target.dwDeviceID;
1251 lpmliA->Target.wMid = mliW.Target.wMid;
1252 lpmliA->Target.wPid = mliW.Target.wPid;
1253 lpmliA->Target.vDriverVersion = mliW.Target.vDriverVersion;
1254 WideCharToMultiByte( CP_ACP, 0, mliW.Target.szPname, -1, lpmliA->Target.szPname,
1255 sizeof(lpmliA->Target.szPname), NULL, NULL );
1260 /**************************************************************************
1261 * mixerSetControlDetails [WINMM.@]
1263 UINT WINAPI mixerSetControlDetails(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcd,
1267 UINT uRet = MMSYSERR_NOERROR;
1269 TRACE("(%p, %p, %08x)\n", hmix, lpmcd, fdwDetails);
1271 if ((uRet = MIXER_GetDev(hmix, fdwDetails, &lpwm)) != MMSYSERR_NOERROR)
1274 return MMDRV_Message(&lpwm->mld, MXDM_SETCONTROLDETAILS, (DWORD_PTR)lpmcd,
1278 /**************************************************************************
1279 * mixerMessage [WINMM.@]
1281 DWORD WINAPI mixerMessage(HMIXER hmix, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
1285 TRACE("(%p, %d, %08lx, %08lx): semi-stub?\n",
1286 hmix, uMsg, dwParam1, dwParam2);
1288 if ((wmld = MMDRV_Get(hmix, MMDRV_MIXER, FALSE)) == NULL)
1289 return MMSYSERR_INVALHANDLE;
1291 return MMDRV_Message(wmld, uMsg, dwParam1, dwParam2);