1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
6 * Copyright 1993 Martin Ayotte
7 * 1998-2002 Eric Pouech
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 * 98/9 added Win32 MCI support
27 * 99/4 added midiStream support
28 * 99/9 added support for loadable low level drivers
34 #define NONAMELESSUNION
35 #define NONAMELESSSTRUCT
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(winmm
);
49 /******************************************************************
52 * Internal wrapper to call USER.UserYield16 (in fact through a Wine only export from USER32).
54 static void MyUserYield(void)
56 HMODULE mod
= GetModuleHandleA( "user32.dll" );
59 FARPROC proc
= GetProcAddress( mod
, "UserYield16" );
64 /* ========================================================================
65 * G L O B A L S E T T I N G S
66 * ========================================================================*/
68 LPWINE_MM_IDATA WINMM_IData
/* = NULL */;
70 /**************************************************************************
71 * WINMM_CreateIData [internal]
73 static BOOL
WINMM_CreateIData(HINSTANCE hInstDLL
)
75 WINMM_IData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WINE_MM_IDATA
));
79 WINMM_IData
->hWinMM32Instance
= hInstDLL
;
80 InitializeCriticalSection(&WINMM_IData
->cs
);
81 WINMM_IData
->cs
.DebugInfo
= (void*)__FILE__
": WinMM";
82 WINMM_IData
->psStopEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
83 WINMM_IData
->psLastEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
84 TRACE("Created IData (%p)\n", WINMM_IData
);
88 /**************************************************************************
89 * WINMM_DeleteIData [internal]
91 static void WINMM_DeleteIData(void)
96 /* FIXME: should also free content and resources allocated
97 * inside WINMM_IData */
98 CloseHandle(WINMM_IData
->psStopEvent
);
99 CloseHandle(WINMM_IData
->psLastEvent
);
100 DeleteCriticalSection(&WINMM_IData
->cs
);
101 HeapFree(GetProcessHeap(), 0, WINMM_IData
);
106 /******************************************************************
110 static HANDLE (WINAPI
*pGetModuleHandle16
)(LPCSTR
);
111 static DWORD (WINAPI
*pLoadLibrary16
)(LPCSTR
);
113 BOOL
WINMM_CheckForMMSystem(void)
115 /* 0 is not checked yet, -1 is not present, 1 is present */
116 static int loaded
/* = 0 */;
120 HANDLE h
= GetModuleHandleA("kernel32");
124 pGetModuleHandle16
= (void*)GetProcAddress(h
, "GetModuleHandle16");
125 pLoadLibrary16
= (void*)GetProcAddress(h
, "LoadLibrary16");
126 if (pGetModuleHandle16
&& pLoadLibrary16
&&
127 (pGetModuleHandle16("MMSYSTEM.DLL") || pLoadLibrary16("MMSYSTEM.DLL")))
134 /**************************************************************************
135 * DllMain (WINMM.init)
137 * WINMM DLL entry point
140 BOOL WINAPI
DllMain(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID fImpLoad
)
142 TRACE("%p 0x%lx %p\n", hInstDLL
, fdwReason
, fImpLoad
);
145 case DLL_PROCESS_ATTACH
:
146 DisableThreadLibraryCalls(hInstDLL
);
148 if (!WINMM_CreateIData(hInstDLL
))
150 if (!MCI_Init() || !MMDRV_Init()) {
155 case DLL_PROCESS_DETACH
:
156 /* close all opened MCI drivers */
157 MCI_SendCommand(MCI_ALL_DEVICE_ID
, MCI_CLOSE
, MCI_WAIT
, 0L, TRUE
);
159 /* now unload all remaining drivers... */
168 /**************************************************************************
169 * Mixer devices. New to Win95
172 /**************************************************************************
173 * find out the real mixer ID depending on hmix (depends on dwFlags)
175 static LPWINE_MIXER
MIXER_GetDev(HMIXEROBJ hmix
, DWORD dwFlags
)
177 LPWINE_MIXER lpwm
= NULL
;
179 switch (dwFlags
& 0xF0000000ul
) {
180 case MIXER_OBJECTF_MIXER
:
181 lpwm
= (LPWINE_MIXER
)MMDRV_Get(hmix
, MMDRV_MIXER
, TRUE
);
183 case MIXER_OBJECTF_HMIXER
:
184 lpwm
= (LPWINE_MIXER
)MMDRV_Get(hmix
, MMDRV_MIXER
, FALSE
);
186 case MIXER_OBJECTF_WAVEOUT
:
187 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEOUT
, TRUE
, MMDRV_MIXER
);
189 case MIXER_OBJECTF_HWAVEOUT
:
190 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEOUT
, FALSE
, MMDRV_MIXER
);
192 case MIXER_OBJECTF_WAVEIN
:
193 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEIN
, TRUE
, MMDRV_MIXER
);
195 case MIXER_OBJECTF_HWAVEIN
:
196 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEIN
, FALSE
, MMDRV_MIXER
);
198 case MIXER_OBJECTF_MIDIOUT
:
199 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIOUT
, TRUE
, MMDRV_MIXER
);
201 case MIXER_OBJECTF_HMIDIOUT
:
202 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIOUT
, FALSE
, MMDRV_MIXER
);
204 case MIXER_OBJECTF_MIDIIN
:
205 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIIN
, TRUE
, MMDRV_MIXER
);
207 case MIXER_OBJECTF_HMIDIIN
:
208 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIIN
, FALSE
, MMDRV_MIXER
);
210 case MIXER_OBJECTF_AUX
:
211 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_AUX
, TRUE
, MMDRV_MIXER
);
214 FIXME("Unsupported flag (%08lx)\n", dwFlags
& 0xF0000000ul
);
220 /**************************************************************************
221 * mixerGetNumDevs [WINMM.@]
223 UINT WINAPI
mixerGetNumDevs(void)
225 return MMDRV_GetNum(MMDRV_MIXER
);
228 /**************************************************************************
229 * mixerGetDevCapsA [WINMM.@]
231 UINT WINAPI
mixerGetDevCapsA(UINT devid
, LPMIXERCAPSA mixcaps
, UINT size
)
235 if ((wmld
= MMDRV_Get((HANDLE
)devid
, MMDRV_MIXER
, TRUE
)) == NULL
)
236 return MMSYSERR_BADDEVICEID
;
238 return MMDRV_Message(wmld
, MXDM_GETDEVCAPS
, (DWORD
)mixcaps
, size
, TRUE
);
241 /**************************************************************************
242 * mixerGetDevCapsW [WINMM.@]
244 UINT WINAPI
mixerGetDevCapsW(UINT devid
, LPMIXERCAPSW mixcaps
, UINT size
)
247 UINT ret
= mixerGetDevCapsA(devid
, &micA
, sizeof(micA
));
249 if (ret
== MMSYSERR_NOERROR
) {
250 mixcaps
->wMid
= micA
.wMid
;
251 mixcaps
->wPid
= micA
.wPid
;
252 mixcaps
->vDriverVersion
= micA
.vDriverVersion
;
253 MultiByteToWideChar( CP_ACP
, 0, micA
.szPname
, -1, mixcaps
->szPname
,
254 sizeof(mixcaps
->szPname
)/sizeof(WCHAR
) );
255 mixcaps
->fdwSupport
= micA
.fdwSupport
;
256 mixcaps
->cDestinations
= micA
.cDestinations
;
261 UINT
MIXER_Open(LPHMIXER lphMix
, UINT uDeviceID
, DWORD dwCallback
,
262 DWORD dwInstance
, DWORD fdwOpen
, BOOL bFrom32
)
269 TRACE("(%p, %d, %08lx, %08lx, %08lx)\n",
270 lphMix
, uDeviceID
, dwCallback
, dwInstance
, fdwOpen
);
272 wmld
= MMDRV_Alloc(sizeof(WINE_MIXER
), MMDRV_MIXER
, &hMix
, &fdwOpen
,
273 &dwCallback
, &dwInstance
, bFrom32
);
275 wmld
->uDeviceID
= uDeviceID
;
276 mod
.hmx
= (HMIXEROBJ
)hMix
;
277 mod
.dwCallback
= dwCallback
;
278 mod
.dwInstance
= dwInstance
;
280 dwRet
= MMDRV_Open(wmld
, MXDM_OPEN
, (DWORD
)&mod
, fdwOpen
);
282 if (dwRet
!= MMSYSERR_NOERROR
) {
283 MMDRV_Free(hMix
, wmld
);
286 if (lphMix
) *lphMix
= hMix
;
287 TRACE("=> %ld hMixer=%p\n", dwRet
, hMix
);
292 /**************************************************************************
293 * mixerOpen [WINMM.@]
295 UINT WINAPI
mixerOpen(LPHMIXER lphMix
, UINT uDeviceID
, DWORD dwCallback
,
296 DWORD dwInstance
, DWORD fdwOpen
)
298 return MIXER_Open(lphMix
, uDeviceID
, dwCallback
, dwInstance
, fdwOpen
, TRUE
);
301 /**************************************************************************
302 * mixerClose [WINMM.@]
304 UINT WINAPI
mixerClose(HMIXER hMix
)
309 TRACE("(%p)\n", hMix
);
311 if ((wmld
= MMDRV_Get(hMix
, MMDRV_MIXER
, FALSE
)) == NULL
) return MMSYSERR_INVALHANDLE
;
313 dwRet
= MMDRV_Close(wmld
, MXDM_CLOSE
);
314 MMDRV_Free(hMix
, wmld
);
319 /**************************************************************************
320 * mixerGetID [WINMM.@]
322 UINT WINAPI
mixerGetID(HMIXEROBJ hmix
, LPUINT lpid
, DWORD fdwID
)
326 TRACE("(%p %p %08lx)\n", hmix
, lpid
, fdwID
);
328 if ((lpwm
= MIXER_GetDev(hmix
, fdwID
)) == NULL
) {
329 return MMSYSERR_INVALHANDLE
;
333 *lpid
= lpwm
->mld
.uDeviceID
;
335 return MMSYSERR_NOERROR
;
338 /**************************************************************************
339 * mixerGetControlDetailsA [WINMM.@]
341 UINT WINAPI
mixerGetControlDetailsA(HMIXEROBJ hmix
, LPMIXERCONTROLDETAILS lpmcdA
,
346 TRACE("(%p, %p, %08lx)\n", hmix
, lpmcdA
, fdwDetails
);
348 if ((lpwm
= MIXER_GetDev(hmix
, fdwDetails
)) == NULL
)
349 return MMSYSERR_INVALHANDLE
;
351 if (lpmcdA
== NULL
|| lpmcdA
->cbStruct
!= sizeof(*lpmcdA
))
352 return MMSYSERR_INVALPARAM
;
354 return MMDRV_Message(&lpwm
->mld
, MXDM_GETCONTROLDETAILS
, (DWORD
)lpmcdA
,
358 /**************************************************************************
359 * mixerGetControlDetailsW [WINMM.@]
361 UINT WINAPI
mixerGetControlDetailsW(HMIXEROBJ hmix
, LPMIXERCONTROLDETAILS lpmcd
, DWORD fdwDetails
)
363 DWORD ret
= MMSYSERR_NOTENABLED
;
365 TRACE("(%p, %p, %08lx)\n", hmix
, lpmcd
, fdwDetails
);
367 if (lpmcd
== NULL
|| lpmcd
->cbStruct
!= sizeof(*lpmcd
))
368 return MMSYSERR_INVALPARAM
;
370 switch (fdwDetails
& MIXER_GETCONTROLDETAILSF_QUERYMASK
) {
371 case MIXER_GETCONTROLDETAILSF_VALUE
:
372 /* can savely use W structure as it is, no string inside */
373 ret
= mixerGetControlDetailsA(hmix
, lpmcd
, fdwDetails
);
375 case MIXER_GETCONTROLDETAILSF_LISTTEXT
:
377 MIXERCONTROLDETAILS_LISTTEXTW
*pDetailsW
= (MIXERCONTROLDETAILS_LISTTEXTW
*)lpmcd
->paDetails
;
378 MIXERCONTROLDETAILS_LISTTEXTA
*pDetailsA
;
379 int size
= max(1, lpmcd
->cChannels
) * sizeof(MIXERCONTROLDETAILS_LISTTEXTA
);
382 if (lpmcd
->u
.cMultipleItems
!= 0) {
383 size
*= lpmcd
->u
.cMultipleItems
;
385 pDetailsA
= (MIXERCONTROLDETAILS_LISTTEXTA
*)HeapAlloc(GetProcessHeap(), 0, size
);
386 lpmcd
->paDetails
= pDetailsA
;
387 lpmcd
->cbDetails
= sizeof(MIXERCONTROLDETAILS_LISTTEXTA
);
388 /* set up lpmcd->paDetails */
389 ret
= mixerGetControlDetailsA(hmix
, lpmcd
, fdwDetails
);
390 /* copy from lpmcd->paDetails back to paDetailsW; */
391 if(ret
== MMSYSERR_NOERROR
) {
392 for(i
=0;i
<lpmcd
->u
.cMultipleItems
*lpmcd
->cChannels
;i
++) {
393 pDetailsW
->dwParam1
= pDetailsA
->dwParam1
;
394 pDetailsW
->dwParam2
= pDetailsA
->dwParam2
;
395 MultiByteToWideChar( CP_ACP
, 0, pDetailsA
->szName
, -1,
397 sizeof(pDetailsW
->szName
)/sizeof(WCHAR
) );
401 pDetailsA
-= lpmcd
->u
.cMultipleItems
*lpmcd
->cChannels
;
402 pDetailsW
-= lpmcd
->u
.cMultipleItems
*lpmcd
->cChannels
;
404 HeapFree(GetProcessHeap(), 0, pDetailsA
);
405 lpmcd
->paDetails
= pDetailsW
;
406 lpmcd
->cbDetails
= sizeof(MIXERCONTROLDETAILS_LISTTEXTW
);
410 ERR("Unsupported fdwDetails=0x%08lx\n", fdwDetails
);
416 /**************************************************************************
417 * mixerGetLineControlsA [WINMM.@]
419 UINT WINAPI
mixerGetLineControlsA(HMIXEROBJ hmix
, LPMIXERLINECONTROLSA lpmlcA
,
424 TRACE("(%p, %p, %08lx)\n", hmix
, lpmlcA
, fdwControls
);
426 if ((lpwm
= MIXER_GetDev(hmix
, fdwControls
)) == NULL
)
427 return MMSYSERR_INVALHANDLE
;
429 if (lpmlcA
== NULL
|| lpmlcA
->cbStruct
!= sizeof(*lpmlcA
))
430 return MMSYSERR_INVALPARAM
;
432 return MMDRV_Message(&lpwm
->mld
, MXDM_GETLINECONTROLS
, (DWORD
)lpmlcA
,
436 /**************************************************************************
437 * mixerGetLineControlsW [WINMM.@]
439 UINT WINAPI
mixerGetLineControlsW(HMIXEROBJ hmix
, LPMIXERLINECONTROLSW lpmlcW
,
442 MIXERLINECONTROLSA mlcA
;
446 TRACE("(%p, %p, %08lx)\n", hmix
, lpmlcW
, fdwControls
);
448 if (lpmlcW
== NULL
|| lpmlcW
->cbStruct
!= sizeof(*lpmlcW
) ||
449 lpmlcW
->cbmxctrl
!= sizeof(MIXERCONTROLW
))
450 return MMSYSERR_INVALPARAM
;
452 mlcA
.cbStruct
= sizeof(mlcA
);
453 mlcA
.dwLineID
= lpmlcW
->dwLineID
;
454 mlcA
.u
.dwControlID
= lpmlcW
->u
.dwControlID
;
455 mlcA
.u
.dwControlType
= lpmlcW
->u
.dwControlType
;
456 mlcA
.cControls
= lpmlcW
->cControls
;
457 mlcA
.cbmxctrl
= sizeof(MIXERCONTROLA
);
458 mlcA
.pamxctrl
= HeapAlloc(GetProcessHeap(), 0,
459 mlcA
.cControls
* mlcA
.cbmxctrl
);
461 ret
= mixerGetLineControlsA(hmix
, &mlcA
, fdwControls
);
463 if (ret
== MMSYSERR_NOERROR
) {
464 lpmlcW
->dwLineID
= mlcA
.dwLineID
;
465 lpmlcW
->u
.dwControlID
= mlcA
.u
.dwControlID
;
466 lpmlcW
->u
.dwControlType
= mlcA
.u
.dwControlType
;
467 lpmlcW
->cControls
= mlcA
.cControls
;
469 for (i
= 0; i
< mlcA
.cControls
; i
++) {
470 lpmlcW
->pamxctrl
[i
].cbStruct
= sizeof(MIXERCONTROLW
);
471 lpmlcW
->pamxctrl
[i
].dwControlID
= mlcA
.pamxctrl
[i
].dwControlID
;
472 lpmlcW
->pamxctrl
[i
].dwControlType
= mlcA
.pamxctrl
[i
].dwControlType
;
473 lpmlcW
->pamxctrl
[i
].fdwControl
= mlcA
.pamxctrl
[i
].fdwControl
;
474 lpmlcW
->pamxctrl
[i
].cMultipleItems
= mlcA
.pamxctrl
[i
].cMultipleItems
;
475 MultiByteToWideChar( CP_ACP
, 0, mlcA
.pamxctrl
[i
].szShortName
, -1,
476 lpmlcW
->pamxctrl
[i
].szShortName
,
477 sizeof(lpmlcW
->pamxctrl
[i
].szShortName
)/sizeof(WCHAR
) );
478 MultiByteToWideChar( CP_ACP
, 0, mlcA
.pamxctrl
[i
].szName
, -1,
479 lpmlcW
->pamxctrl
[i
].szName
,
480 sizeof(lpmlcW
->pamxctrl
[i
].szName
)/sizeof(WCHAR
) );
481 /* sizeof(lpmlcW->pamxctrl[i].Bounds) ==
482 * sizeof(mlcA.pamxctrl[i].Bounds) */
483 memcpy(&lpmlcW
->pamxctrl
[i
].Bounds
, &mlcA
.pamxctrl
[i
].Bounds
,
484 sizeof(mlcA
.pamxctrl
[i
].Bounds
));
485 /* sizeof(lpmlcW->pamxctrl[i].Metrics) ==
486 * sizeof(mlcA.pamxctrl[i].Metrics) */
487 memcpy(&lpmlcW
->pamxctrl
[i
].Metrics
, &mlcA
.pamxctrl
[i
].Metrics
,
488 sizeof(mlcA
.pamxctrl
[i
].Metrics
));
492 HeapFree(GetProcessHeap(), 0, mlcA
.pamxctrl
);
497 /**************************************************************************
498 * mixerGetLineInfoA [WINMM.@]
500 UINT WINAPI
mixerGetLineInfoA(HMIXEROBJ hmix
, LPMIXERLINEA lpmliW
, DWORD fdwInfo
)
504 TRACE("(%p, %p, %08lx)\n", hmix
, lpmliW
, fdwInfo
);
506 if ((lpwm
= MIXER_GetDev(hmix
, fdwInfo
)) == NULL
)
507 return MMSYSERR_INVALHANDLE
;
509 return MMDRV_Message(&lpwm
->mld
, MXDM_GETLINEINFO
, (DWORD
)lpmliW
,
513 /**************************************************************************
514 * mixerGetLineInfoW [WINMM.@]
516 UINT WINAPI
mixerGetLineInfoW(HMIXEROBJ hmix
, LPMIXERLINEW lpmliW
,
522 TRACE("(%p, %p, %08lx)\n", hmix
, lpmliW
, fdwInfo
);
524 if (lpmliW
== NULL
|| lpmliW
->cbStruct
!= sizeof(*lpmliW
))
525 return MMSYSERR_INVALPARAM
;
527 mliA
.cbStruct
= sizeof(mliA
);
528 switch (fdwInfo
& MIXER_GETLINEINFOF_QUERYMASK
) {
529 case MIXER_GETLINEINFOF_COMPONENTTYPE
:
530 mliA
.dwComponentType
= lpmliW
->dwComponentType
;
532 case MIXER_GETLINEINFOF_DESTINATION
:
533 mliA
.dwDestination
= lpmliW
->dwDestination
;
535 case MIXER_GETLINEINFOF_LINEID
:
536 mliA
.dwLineID
= lpmliW
->dwLineID
;
538 case MIXER_GETLINEINFOF_SOURCE
:
539 mliA
.dwDestination
= lpmliW
->dwDestination
;
540 mliA
.dwSource
= lpmliW
->dwSource
;
542 case MIXER_GETLINEINFOF_TARGETTYPE
:
543 mliA
.Target
.dwType
= lpmliW
->Target
.dwType
;
544 mliA
.Target
.wMid
= lpmliW
->Target
.wMid
;
545 mliA
.Target
.wPid
= lpmliW
->Target
.wPid
;
546 mliA
.Target
.vDriverVersion
= lpmliW
->Target
.vDriverVersion
;
547 WideCharToMultiByte( CP_ACP
, 0, lpmliW
->Target
.szPname
, -1, mliA
.Target
.szPname
, sizeof(mliA
.Target
.szPname
), NULL
, NULL
);
550 FIXME("Unsupported fdwControls=0x%08lx\n", fdwInfo
);
553 ret
= mixerGetLineInfoA(hmix
, &mliA
, fdwInfo
);
555 lpmliW
->dwDestination
= mliA
.dwDestination
;
556 lpmliW
->dwSource
= mliA
.dwSource
;
557 lpmliW
->dwLineID
= mliA
.dwLineID
;
558 lpmliW
->fdwLine
= mliA
.fdwLine
;
559 lpmliW
->dwUser
= mliA
.dwUser
;
560 lpmliW
->dwComponentType
= mliA
.dwComponentType
;
561 lpmliW
->cChannels
= mliA
.cChannels
;
562 lpmliW
->cConnections
= mliA
.cConnections
;
563 lpmliW
->cControls
= mliA
.cControls
;
564 MultiByteToWideChar( CP_ACP
, 0, mliA
.szShortName
, -1, lpmliW
->szShortName
,
565 sizeof(lpmliW
->szShortName
)/sizeof(WCHAR
) );
566 MultiByteToWideChar( CP_ACP
, 0, mliA
.szName
, -1, lpmliW
->szName
,
567 sizeof(lpmliW
->szName
)/sizeof(WCHAR
) );
568 lpmliW
->Target
.dwType
= mliA
.Target
.dwType
;
569 lpmliW
->Target
.dwDeviceID
= mliA
.Target
.dwDeviceID
;
570 lpmliW
->Target
.wMid
= mliA
.Target
.wMid
;
571 lpmliW
->Target
.wPid
= mliA
.Target
.wPid
;
572 lpmliW
->Target
.vDriverVersion
= mliA
.Target
.vDriverVersion
;
573 MultiByteToWideChar( CP_ACP
, 0, mliA
.Target
.szPname
, -1, lpmliW
->Target
.szPname
,
574 sizeof(lpmliW
->Target
.szPname
)/sizeof(WCHAR
) );
579 /**************************************************************************
580 * mixerSetControlDetails [WINMM.@]
582 UINT WINAPI
mixerSetControlDetails(HMIXEROBJ hmix
, LPMIXERCONTROLDETAILS lpmcdA
,
587 TRACE("(%p, %p, %08lx)\n", hmix
, lpmcdA
, fdwDetails
);
589 if ((lpwm
= MIXER_GetDev(hmix
, fdwDetails
)) == NULL
)
590 return MMSYSERR_INVALHANDLE
;
592 return MMDRV_Message(&lpwm
->mld
, MXDM_SETCONTROLDETAILS
, (DWORD
)lpmcdA
,
596 /**************************************************************************
597 * mixerMessage [WINMM.@]
599 UINT WINAPI
mixerMessage(HMIXER hmix
, UINT uMsg
, DWORD dwParam1
, DWORD dwParam2
)
603 TRACE("(%04lx, %d, %08lx, %08lx): semi-stub?\n",
604 (DWORD
)hmix
, uMsg
, dwParam1
, dwParam2
);
606 if ((wmld
= MMDRV_Get(hmix
, MMDRV_MIXER
, FALSE
)) == NULL
)
607 return MMSYSERR_INVALHANDLE
;
609 return MMDRV_Message(wmld
, uMsg
, dwParam1
, dwParam2
, TRUE
);
612 /**************************************************************************
613 * auxGetNumDevs [WINMM.@]
615 UINT WINAPI
auxGetNumDevs(void)
617 return MMDRV_GetNum(MMDRV_AUX
);
620 /**************************************************************************
621 * auxGetDevCapsW [WINMM.@]
623 UINT WINAPI
auxGetDevCapsW(UINT uDeviceID
, LPAUXCAPSW lpCaps
, UINT uSize
)
626 UINT ret
= auxGetDevCapsA(uDeviceID
, &acA
, sizeof(acA
));
628 lpCaps
->wMid
= acA
.wMid
;
629 lpCaps
->wPid
= acA
.wPid
;
630 lpCaps
->vDriverVersion
= acA
.vDriverVersion
;
631 MultiByteToWideChar( CP_ACP
, 0, acA
.szPname
, -1, lpCaps
->szPname
,
632 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
633 lpCaps
->wTechnology
= acA
.wTechnology
;
634 lpCaps
->dwSupport
= acA
.dwSupport
;
638 /**************************************************************************
639 * auxGetDevCapsA [WINMM.@]
641 UINT WINAPI
auxGetDevCapsA(UINT uDeviceID
, LPAUXCAPSA lpCaps
, UINT uSize
)
645 TRACE("(%04X, %p, %d) !\n", uDeviceID
, lpCaps
, uSize
);
647 if ((wmld
= MMDRV_Get((HANDLE
)uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
648 return MMSYSERR_INVALHANDLE
;
649 return MMDRV_Message(wmld
, AUXDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
652 /**************************************************************************
653 * auxGetVolume [WINMM.@]
655 UINT WINAPI
auxGetVolume(UINT uDeviceID
, DWORD
* lpdwVolume
)
659 TRACE("(%04X, %p) !\n", uDeviceID
, lpdwVolume
);
661 if ((wmld
= MMDRV_Get((HANDLE
)uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
662 return MMSYSERR_INVALHANDLE
;
663 return MMDRV_Message(wmld
, AUXDM_GETVOLUME
, (DWORD
)lpdwVolume
, 0L, TRUE
);
666 /**************************************************************************
667 * auxSetVolume [WINMM.@]
669 UINT WINAPI
auxSetVolume(UINT uDeviceID
, DWORD dwVolume
)
673 TRACE("(%04X, %lu) !\n", uDeviceID
, dwVolume
);
675 if ((wmld
= MMDRV_Get((HANDLE
)uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
676 return MMSYSERR_INVALHANDLE
;
677 return MMDRV_Message(wmld
, AUXDM_SETVOLUME
, dwVolume
, 0L, TRUE
);
680 /**************************************************************************
681 * auxOutMessage [WINMM.@]
683 UINT WINAPI
auxOutMessage(UINT uDeviceID
, UINT uMessage
, DWORD dw1
, DWORD dw2
)
687 if ((wmld
= MMDRV_Get((HANDLE
)uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
688 return MMSYSERR_INVALHANDLE
;
690 return MMDRV_Message(wmld
, uMessage
, dw1
, dw2
, TRUE
);
693 /**************************************************************************
694 * mciGetErrorStringW [WINMM.@]
696 BOOL WINAPI
mciGetErrorStringW(DWORD wError
, LPWSTR lpstrBuffer
, UINT uLength
)
698 LPSTR bufstr
= HeapAlloc(GetProcessHeap(), 0, uLength
);
699 BOOL ret
= mciGetErrorStringA(wError
, bufstr
, uLength
);
701 MultiByteToWideChar( CP_ACP
, 0, bufstr
, -1, lpstrBuffer
, uLength
);
702 HeapFree(GetProcessHeap(), 0, bufstr
);
706 /**************************************************************************
707 * mciGetErrorStringA [WINMM.@]
709 BOOL WINAPI
mciGetErrorStringA(DWORD dwError
, LPSTR lpstrBuffer
, UINT uLength
)
713 if (lpstrBuffer
!= NULL
&& uLength
> 0 &&
714 dwError
>= MCIERR_BASE
&& dwError
<= MCIERR_CUSTOM_DRIVER_BASE
) {
716 if (LoadStringA(WINMM_IData
->hWinMM32Instance
,
717 dwError
, lpstrBuffer
, uLength
) > 0) {
724 /**************************************************************************
725 * mciDriverNotify [WINMM.@]
727 BOOL WINAPI
mciDriverNotify(HWND hWndCallBack
, UINT wDevID
, UINT wStatus
)
730 TRACE("(%p, %04x, %04X)\n", hWndCallBack
, wDevID
, wStatus
);
732 return PostMessageA(hWndCallBack
, MM_MCINOTIFY
, wStatus
, wDevID
);
735 /**************************************************************************
736 * mciGetDriverData [WINMM.@]
738 DWORD WINAPI
mciGetDriverData(UINT uDeviceID
)
740 LPWINE_MCIDRIVER wmd
;
742 TRACE("(%04x)\n", uDeviceID
);
744 wmd
= MCI_GetDriver(uDeviceID
);
747 WARN("Bad uDeviceID\n");
751 return wmd
->dwPrivate
;
754 /**************************************************************************
755 * mciSetDriverData [WINMM.@]
757 BOOL WINAPI
mciSetDriverData(UINT uDeviceID
, DWORD data
)
759 LPWINE_MCIDRIVER wmd
;
761 TRACE("(%04x, %08lx)\n", uDeviceID
, data
);
763 wmd
= MCI_GetDriver(uDeviceID
);
766 WARN("Bad uDeviceID\n");
770 wmd
->dwPrivate
= data
;
774 /**************************************************************************
775 * mciSendCommandA [WINMM.@]
777 DWORD WINAPI
mciSendCommandA(UINT wDevID
, UINT wMsg
, DWORD dwParam1
, DWORD dwParam2
)
781 TRACE("(%08x, %s, %08lx, %08lx)\n",
782 wDevID
, MCI_MessageToString(wMsg
), dwParam1
, dwParam2
);
784 dwRet
= MCI_SendCommand(wDevID
, wMsg
, dwParam1
, dwParam2
, TRUE
);
785 dwRet
= MCI_CleanUp(dwRet
, wMsg
, dwParam2
);
786 TRACE("=> %08lx\n", dwRet
);
790 /**************************************************************************
791 * mciSendCommandW [WINMM.@]
793 DWORD WINAPI
mciSendCommandW(UINT wDevID
, UINT wMsg
, DWORD dwParam1
, DWORD dwParam2
)
795 FIXME("(%08x, %s, %08lx, %08lx): stub\n",
796 wDevID
, MCI_MessageToString(wMsg
), dwParam1
, dwParam2
);
797 return MCIERR_UNSUPPORTED_FUNCTION
;
800 /**************************************************************************
801 * mciGetDeviceIDA [WINMM.@]
803 UINT WINAPI
mciGetDeviceIDA(LPCSTR lpstrName
)
805 return MCI_GetDriverFromString(lpstrName
);
808 /**************************************************************************
809 * mciGetDeviceIDW [WINMM.@]
811 UINT WINAPI
mciGetDeviceIDW(LPCWSTR lpwstrName
)
813 LPSTR lpstrName
= NULL
;
818 len
= WideCharToMultiByte( CP_ACP
, 0, lpwstrName
, -1, NULL
, 0, NULL
, NULL
);
819 lpstrName
= HeapAlloc( GetProcessHeap(), 0, len
);
820 if (lpstrName
) WideCharToMultiByte( CP_ACP
, 0, lpwstrName
, -1, lpstrName
, len
, NULL
, NULL
);
822 ret
= MCI_GetDriverFromString(lpstrName
);
823 HeapFree(GetProcessHeap(), 0, lpstrName
);
827 /**************************************************************************
828 * MCI_DefYieldProc [internal]
830 UINT WINAPI
MCI_DefYieldProc(MCIDEVICEID wDevID
, DWORD data
)
834 TRACE("(0x%04x, 0x%08lx)\n", wDevID
, data
);
836 if ((HIWORD(data
) != 0 && HWND_16(GetActiveWindow()) != HIWORD(data
)) ||
837 (GetAsyncKeyState(LOWORD(data
)) & 1) == 0) {
843 msg
.hwnd
= HWND_32(HIWORD(data
));
844 while (!PeekMessageA(&msg
, msg
.hwnd
, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
));
850 /**************************************************************************
851 * mciSetYieldProc [WINMM.@]
853 BOOL WINAPI
mciSetYieldProc(UINT uDeviceID
, YIELDPROC fpYieldProc
, DWORD dwYieldData
)
855 LPWINE_MCIDRIVER wmd
;
857 TRACE("(%u, %p, %08lx)\n", uDeviceID
, fpYieldProc
, dwYieldData
);
859 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
860 WARN("Bad uDeviceID\n");
864 wmd
->lpfnYieldProc
= fpYieldProc
;
865 wmd
->dwYieldData
= dwYieldData
;
871 /**************************************************************************
872 * mciGetDeviceIDFromElementIDW [WINMM.@]
874 UINT WINAPI
mciGetDeviceIDFromElementIDW(DWORD dwElementID
, LPCWSTR lpstrType
)
876 /* FIXME: that's rather strange, there is no
877 * mciGetDeviceIDFromElementID32A in winmm.spec
879 FIXME("(%lu, %p) stub\n", dwElementID
, lpstrType
);
883 /**************************************************************************
884 * mciGetYieldProc [WINMM.@]
886 YIELDPROC WINAPI
mciGetYieldProc(UINT uDeviceID
, DWORD
* lpdwYieldData
)
888 LPWINE_MCIDRIVER wmd
;
890 TRACE("(%u, %p)\n", uDeviceID
, lpdwYieldData
);
892 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
893 WARN("Bad uDeviceID\n");
896 if (!wmd
->lpfnYieldProc
) {
897 WARN("No proc set\n");
901 WARN("Proc is 32 bit\n");
904 return wmd
->lpfnYieldProc
;
907 /**************************************************************************
908 * mciGetCreatorTask [WINMM.@]
910 HTASK WINAPI
mciGetCreatorTask(UINT uDeviceID
)
912 LPWINE_MCIDRIVER wmd
;
915 if ((wmd
= MCI_GetDriver(uDeviceID
))) ret
= (HTASK
)wmd
->CreatorThread
;
917 TRACE("(%u) => %p\n", uDeviceID
, ret
);
921 /**************************************************************************
922 * mciDriverYield [WINMM.@]
924 UINT WINAPI
mciDriverYield(UINT uDeviceID
)
926 LPWINE_MCIDRIVER wmd
;
929 TRACE("(%04x)\n", uDeviceID
);
931 if (!(wmd
= MCI_GetDriver(uDeviceID
)) || !wmd
->lpfnYieldProc
|| !wmd
->bIs32
) {
934 ret
= wmd
->lpfnYieldProc(uDeviceID
, wmd
->dwYieldData
);
940 /**************************************************************************
941 * midiOutGetNumDevs [WINMM.@]
943 UINT WINAPI
midiOutGetNumDevs(void)
945 return MMDRV_GetNum(MMDRV_MIDIOUT
);
948 /**************************************************************************
949 * midiOutGetDevCapsW [WINMM.@]
951 UINT WINAPI
midiOutGetDevCapsW(UINT uDeviceID
, LPMIDIOUTCAPSW lpCaps
,
957 ret
= midiOutGetDevCapsA(uDeviceID
, &mocA
, sizeof(mocA
));
958 lpCaps
->wMid
= mocA
.wMid
;
959 lpCaps
->wPid
= mocA
.wPid
;
960 lpCaps
->vDriverVersion
= mocA
.vDriverVersion
;
961 MultiByteToWideChar( CP_ACP
, 0, mocA
.szPname
, -1, lpCaps
->szPname
,
962 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
963 lpCaps
->wTechnology
= mocA
.wTechnology
;
964 lpCaps
->wVoices
= mocA
.wVoices
;
965 lpCaps
->wNotes
= mocA
.wNotes
;
966 lpCaps
->wChannelMask
= mocA
.wChannelMask
;
967 lpCaps
->dwSupport
= mocA
.dwSupport
;
971 /**************************************************************************
972 * midiOutGetDevCapsA [WINMM.@]
974 UINT WINAPI
midiOutGetDevCapsA(UINT uDeviceID
, LPMIDIOUTCAPSA lpCaps
,
979 TRACE("(%u, %p, %u);\n", uDeviceID
, lpCaps
, uSize
);
981 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
983 if ((wmld
= MMDRV_Get((HANDLE
)uDeviceID
, MMDRV_MIDIOUT
, TRUE
)) == NULL
)
984 return MMSYSERR_INVALHANDLE
;
986 return MMDRV_Message(wmld
, MODM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
989 /**************************************************************************
990 * MIDI_GetErrorText [internal]
992 static UINT16
MIDI_GetErrorText(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
994 UINT16 ret
= MMSYSERR_BADERRNUM
;
996 if (lpText
== NULL
) {
997 ret
= MMSYSERR_INVALPARAM
;
998 } else if (uSize
== 0) {
999 ret
= MMSYSERR_NOERROR
;
1001 /* test has been removed 'coz MMSYSERR_BASE is 0, and gcc did emit
1002 * a warning for the test was always true */
1003 (/*uError >= MMSYSERR_BASE && */ uError
<= MMSYSERR_LASTERROR
) ||
1004 (uError
>= MIDIERR_BASE
&& uError
<= MIDIERR_LASTERROR
)) {
1006 if (LoadStringA(WINMM_IData
->hWinMM32Instance
,
1007 uError
, lpText
, uSize
) > 0) {
1008 ret
= MMSYSERR_NOERROR
;
1014 /**************************************************************************
1015 * midiOutGetErrorTextA [WINMM.@]
1017 UINT WINAPI
midiOutGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
1019 return MIDI_GetErrorText(uError
, lpText
, uSize
);
1022 /**************************************************************************
1023 * midiOutGetErrorTextW [WINMM.@]
1025 UINT WINAPI
midiOutGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
1027 LPSTR xstr
= HeapAlloc(GetProcessHeap(), 0, uSize
);
1030 ret
= MIDI_GetErrorText(uError
, xstr
, uSize
);
1031 MultiByteToWideChar( CP_ACP
, 0, xstr
, -1, lpText
, uSize
);
1032 HeapFree(GetProcessHeap(), 0, xstr
);
1036 /**************************************************************************
1037 * MIDI_OutAlloc [internal]
1039 static LPWINE_MIDI
MIDI_OutAlloc(HMIDIOUT
* lphMidiOut
, LPDWORD lpdwCallback
,
1040 LPDWORD lpdwInstance
, LPDWORD lpdwFlags
,
1041 DWORD cIDs
, MIDIOPENSTRMID
* lpIDs
, BOOL bFrom32
)
1047 size
= sizeof(WINE_MIDI
) + (cIDs
? (cIDs
-1) : 0) * sizeof(MIDIOPENSTRMID
);
1049 lpwm
= (LPWINE_MIDI
)MMDRV_Alloc(size
, MMDRV_MIDIOUT
, &hMidiOut
, lpdwFlags
,
1050 lpdwCallback
, lpdwInstance
, bFrom32
);
1052 if (lphMidiOut
!= NULL
)
1053 *lphMidiOut
= hMidiOut
;
1056 lpwm
->mod
.hMidi
= (HMIDI
) hMidiOut
;
1057 lpwm
->mod
.dwCallback
= *lpdwCallback
;
1058 lpwm
->mod
.dwInstance
= *lpdwInstance
;
1059 lpwm
->mod
.dnDevNode
= 0;
1060 lpwm
->mod
.cIds
= cIDs
;
1062 memcpy(&(lpwm
->mod
.rgIds
), lpIDs
, cIDs
* sizeof(MIDIOPENSTRMID
));
1067 UINT
MIDI_OutOpen(HMIDIOUT
* lphMidiOut
, UINT uDeviceID
, DWORD dwCallback
,
1068 DWORD dwInstance
, DWORD dwFlags
, BOOL bFrom32
)
1074 TRACE("(%p, %d, %08lX, %08lX, %08lX);\n",
1075 lphMidiOut
, uDeviceID
, dwCallback
, dwInstance
, dwFlags
);
1077 if (lphMidiOut
!= NULL
) *lphMidiOut
= 0;
1079 lpwm
= MIDI_OutAlloc(&hMidiOut
, &dwCallback
, &dwInstance
, &dwFlags
,
1083 return MMSYSERR_NOMEM
;
1085 lpwm
->mld
.uDeviceID
= uDeviceID
;
1087 dwRet
= MMDRV_Open((LPWINE_MLD
)lpwm
, MODM_OPEN
, (DWORD
)&lpwm
->mod
, dwFlags
);
1089 if (dwRet
!= MMSYSERR_NOERROR
) {
1090 MMDRV_Free(hMidiOut
, (LPWINE_MLD
)lpwm
);
1094 if (lphMidiOut
) *lphMidiOut
= hMidiOut
;
1095 TRACE("=> %d hMidi=%p\n", dwRet
, hMidiOut
);
1100 /**************************************************************************
1101 * midiOutOpen [WINMM.@]
1103 UINT WINAPI
midiOutOpen(HMIDIOUT
* lphMidiOut
, UINT uDeviceID
,
1104 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
1106 return MIDI_OutOpen(lphMidiOut
, uDeviceID
, dwCallback
, dwInstance
, dwFlags
, TRUE
);
1109 /**************************************************************************
1110 * midiOutClose [WINMM.@]
1112 UINT WINAPI
midiOutClose(HMIDIOUT hMidiOut
)
1117 TRACE("(%p)\n", hMidiOut
);
1119 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
1120 return MMSYSERR_INVALHANDLE
;
1122 dwRet
= MMDRV_Close(wmld
, MODM_CLOSE
);
1123 MMDRV_Free(hMidiOut
, wmld
);
1128 /**************************************************************************
1129 * midiOutPrepareHeader [WINMM.@]
1131 UINT WINAPI
midiOutPrepareHeader(HMIDIOUT hMidiOut
,
1132 MIDIHDR
* lpMidiOutHdr
, UINT uSize
)
1136 TRACE("(%p, %p, %d)\n", hMidiOut
, lpMidiOutHdr
, uSize
);
1138 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
1139 return MMSYSERR_INVALHANDLE
;
1141 return MMDRV_Message(wmld
, MODM_PREPARE
, (DWORD
)lpMidiOutHdr
, uSize
, TRUE
);
1144 /**************************************************************************
1145 * midiOutUnprepareHeader [WINMM.@]
1147 UINT WINAPI
midiOutUnprepareHeader(HMIDIOUT hMidiOut
,
1148 MIDIHDR
* lpMidiOutHdr
, UINT uSize
)
1152 TRACE("(%p, %p, %d)\n", hMidiOut
, lpMidiOutHdr
, uSize
);
1154 if (!(lpMidiOutHdr
->dwFlags
& MHDR_PREPARED
)) {
1155 return MMSYSERR_NOERROR
;
1158 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
1159 return MMSYSERR_INVALHANDLE
;
1161 return MMDRV_Message(wmld
, MODM_UNPREPARE
, (DWORD
)lpMidiOutHdr
, uSize
, TRUE
);
1164 /**************************************************************************
1165 * midiOutShortMsg [WINMM.@]
1167 UINT WINAPI
midiOutShortMsg(HMIDIOUT hMidiOut
, DWORD dwMsg
)
1171 TRACE("(%p, %08lX)\n", hMidiOut
, dwMsg
);
1173 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
1174 return MMSYSERR_INVALHANDLE
;
1176 return MMDRV_Message(wmld
, MODM_DATA
, dwMsg
, 0L, TRUE
);
1179 /**************************************************************************
1180 * midiOutLongMsg [WINMM.@]
1182 UINT WINAPI
midiOutLongMsg(HMIDIOUT hMidiOut
,
1183 MIDIHDR
* lpMidiOutHdr
, UINT uSize
)
1187 TRACE("(%p, %p, %d)\n", hMidiOut
, lpMidiOutHdr
, uSize
);
1189 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
1190 return MMSYSERR_INVALHANDLE
;
1192 return MMDRV_Message(wmld
, MODM_LONGDATA
, (DWORD
)lpMidiOutHdr
, uSize
, TRUE
);
1195 /**************************************************************************
1196 * midiOutReset [WINMM.@]
1198 UINT WINAPI
midiOutReset(HMIDIOUT hMidiOut
)
1202 TRACE("(%p)\n", hMidiOut
);
1204 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
1205 return MMSYSERR_INVALHANDLE
;
1207 return MMDRV_Message(wmld
, MODM_RESET
, 0L, 0L, TRUE
);
1210 /**************************************************************************
1211 * midiOutGetVolume [WINMM.@]
1213 UINT WINAPI
midiOutGetVolume(HMIDIOUT hMidiOut
, DWORD
* lpdwVolume
)
1217 TRACE("(%p, %p);\n", hMidiOut
, lpdwVolume
);
1219 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, TRUE
)) == NULL
)
1220 return MMSYSERR_INVALHANDLE
;
1222 return MMDRV_Message(wmld
, MODM_GETVOLUME
, (DWORD
)lpdwVolume
, 0L, TRUE
);
1225 /**************************************************************************
1226 * midiOutSetVolume [WINMM.@]
1228 UINT WINAPI
midiOutSetVolume(HMIDIOUT hMidiOut
, DWORD dwVolume
)
1232 TRACE("(%p, %ld);\n", hMidiOut
, dwVolume
);
1234 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, TRUE
)) == NULL
)
1235 return MMSYSERR_INVALHANDLE
;
1237 return MMDRV_Message(wmld
, MODM_SETVOLUME
, dwVolume
, 0L, TRUE
);
1240 /**************************************************************************
1241 * midiOutCachePatches [WINMM.@]
1243 UINT WINAPI
midiOutCachePatches(HMIDIOUT hMidiOut
, UINT uBank
,
1244 WORD
* lpwPatchArray
, UINT uFlags
)
1246 /* not really necessary to support this */
1247 FIXME("not supported yet\n");
1248 return MMSYSERR_NOTSUPPORTED
;
1251 /**************************************************************************
1252 * midiOutCacheDrumPatches [WINMM.@]
1254 UINT WINAPI
midiOutCacheDrumPatches(HMIDIOUT hMidiOut
, UINT uPatch
,
1255 WORD
* lpwKeyArray
, UINT uFlags
)
1257 FIXME("not supported yet\n");
1258 return MMSYSERR_NOTSUPPORTED
;
1261 /**************************************************************************
1262 * midiOutGetID [WINMM.@]
1264 UINT WINAPI
midiOutGetID(HMIDIOUT hMidiOut
, UINT
* lpuDeviceID
)
1268 TRACE("(%p, %p)\n", hMidiOut
, lpuDeviceID
);
1270 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
1271 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
1272 return MMSYSERR_INVALHANDLE
;
1274 *lpuDeviceID
= wmld
->uDeviceID
;
1275 return MMSYSERR_NOERROR
;
1278 /**************************************************************************
1279 * midiOutMessage [WINMM.@]
1281 UINT WINAPI
midiOutMessage(HMIDIOUT hMidiOut
, UINT uMessage
,
1282 DWORD dwParam1
, DWORD dwParam2
)
1286 TRACE("(%p, %04X, %08lX, %08lX)\n", hMidiOut
, uMessage
, dwParam1
, dwParam2
);
1288 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
) {
1290 if (uMessage
== 0x0001) {
1291 *(LPDWORD
)dwParam1
= 1;
1294 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, TRUE
)) != NULL
) {
1295 return MMDRV_PhysicalFeatures(wmld
, uMessage
, dwParam1
, dwParam2
);
1297 return MMSYSERR_INVALHANDLE
;
1303 FIXME("can't handle OPEN or CLOSE message!\n");
1304 return MMSYSERR_NOTSUPPORTED
;
1306 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
1309 /**************************************************************************
1310 * midiInGetNumDevs [WINMM.@]
1312 UINT WINAPI
midiInGetNumDevs(void)
1314 return MMDRV_GetNum(MMDRV_MIDIIN
);
1317 /**************************************************************************
1318 * midiInGetDevCapsW [WINMM.@]
1320 UINT WINAPI
midiInGetDevCapsW(UINT uDeviceID
, LPMIDIINCAPSW lpCaps
, UINT uSize
)
1323 UINT ret
= midiInGetDevCapsA(uDeviceID
, &micA
, uSize
);
1325 if (ret
== MMSYSERR_NOERROR
) {
1326 lpCaps
->wMid
= micA
.wMid
;
1327 lpCaps
->wPid
= micA
.wPid
;
1328 lpCaps
->vDriverVersion
= micA
.vDriverVersion
;
1329 MultiByteToWideChar( CP_ACP
, 0, micA
.szPname
, -1, lpCaps
->szPname
,
1330 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
1331 lpCaps
->dwSupport
= micA
.dwSupport
;
1336 /**************************************************************************
1337 * midiInGetDevCapsA [WINMM.@]
1339 UINT WINAPI
midiInGetDevCapsA(UINT uDeviceID
, LPMIDIINCAPSA lpCaps
, UINT uSize
)
1343 TRACE("(%d, %p, %d);\n", uDeviceID
, lpCaps
, uSize
);
1345 if ((wmld
= MMDRV_Get((HANDLE
)uDeviceID
, MMDRV_MIDIIN
, TRUE
)) == NULL
)
1346 return MMSYSERR_INVALHANDLE
;
1348 return MMDRV_Message(wmld
, MIDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
1351 /**************************************************************************
1352 * midiInGetErrorTextW [WINMM.@]
1354 UINT WINAPI
midiInGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
1356 LPSTR xstr
= HeapAlloc(GetProcessHeap(), 0, uSize
);
1357 UINT ret
= MIDI_GetErrorText(uError
, xstr
, uSize
);
1359 MultiByteToWideChar( CP_ACP
, 0, xstr
, -1, lpText
, uSize
);
1360 HeapFree(GetProcessHeap(), 0, xstr
);
1364 /**************************************************************************
1365 * midiInGetErrorTextA [WINMM.@]
1367 UINT WINAPI
midiInGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
1369 return MIDI_GetErrorText(uError
, lpText
, uSize
);
1372 UINT
MIDI_InOpen(HMIDIIN
* lphMidiIn
, UINT uDeviceID
, DWORD dwCallback
,
1373 DWORD dwInstance
, DWORD dwFlags
, BOOL bFrom32
)
1379 TRACE("(%p, %d, %08lX, %08lX, %08lX);\n",
1380 lphMidiIn
, uDeviceID
, dwCallback
, dwInstance
, dwFlags
);
1382 if (lphMidiIn
!= NULL
) *lphMidiIn
= 0;
1384 lpwm
= (LPWINE_MIDI
)MMDRV_Alloc(sizeof(WINE_MIDI
), MMDRV_MIDIIN
, &hMidiIn
,
1385 &dwFlags
, &dwCallback
, &dwInstance
, bFrom32
);
1388 return MMSYSERR_NOMEM
;
1390 lpwm
->mod
.hMidi
= (HMIDI
) hMidiIn
;
1391 lpwm
->mod
.dwCallback
= dwCallback
;
1392 lpwm
->mod
.dwInstance
= dwInstance
;
1394 lpwm
->mld
.uDeviceID
= uDeviceID
;
1395 dwRet
= MMDRV_Open(&lpwm
->mld
, MIDM_OPEN
, (DWORD
)&lpwm
->mod
, dwFlags
);
1397 if (dwRet
!= MMSYSERR_NOERROR
) {
1398 MMDRV_Free(hMidiIn
, &lpwm
->mld
);
1401 if (lphMidiIn
!= NULL
) *lphMidiIn
= hMidiIn
;
1402 TRACE("=> %ld hMidi=%p\n", dwRet
, hMidiIn
);
1407 /**************************************************************************
1408 * midiInOpen [WINMM.@]
1410 UINT WINAPI
midiInOpen(HMIDIIN
* lphMidiIn
, UINT uDeviceID
,
1411 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
1413 return MIDI_InOpen(lphMidiIn
, uDeviceID
, dwCallback
, dwInstance
, dwFlags
, TRUE
);
1416 /**************************************************************************
1417 * midiInClose [WINMM.@]
1419 UINT WINAPI
midiInClose(HMIDIIN hMidiIn
)
1424 TRACE("(%p)\n", hMidiIn
);
1426 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
1427 return MMSYSERR_INVALHANDLE
;
1429 dwRet
= MMDRV_Close(wmld
, MIDM_CLOSE
);
1430 MMDRV_Free(hMidiIn
, wmld
);
1434 /**************************************************************************
1435 * midiInPrepareHeader [WINMM.@]
1437 UINT WINAPI
midiInPrepareHeader(HMIDIIN hMidiIn
,
1438 MIDIHDR
* lpMidiInHdr
, UINT uSize
)
1442 TRACE("(%p, %p, %d)\n", hMidiIn
, lpMidiInHdr
, uSize
);
1444 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
1445 return MMSYSERR_INVALHANDLE
;
1447 return MMDRV_Message(wmld
, MIDM_PREPARE
, (DWORD
)lpMidiInHdr
, uSize
, TRUE
);
1450 /**************************************************************************
1451 * midiInUnprepareHeader [WINMM.@]
1453 UINT WINAPI
midiInUnprepareHeader(HMIDIIN hMidiIn
,
1454 MIDIHDR
* lpMidiInHdr
, UINT uSize
)
1458 TRACE("(%p, %p, %d)\n", hMidiIn
, lpMidiInHdr
, uSize
);
1460 if (!(lpMidiInHdr
->dwFlags
& MHDR_PREPARED
)) {
1461 return MMSYSERR_NOERROR
;
1464 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
1465 return MMSYSERR_INVALHANDLE
;
1467 return MMDRV_Message(wmld
, MIDM_UNPREPARE
, (DWORD
)lpMidiInHdr
, uSize
, TRUE
);
1470 /**************************************************************************
1471 * midiInAddBuffer [WINMM.@]
1473 UINT WINAPI
midiInAddBuffer(HMIDIIN hMidiIn
,
1474 MIDIHDR
* lpMidiInHdr
, UINT uSize
)
1478 TRACE("(%p, %p, %d)\n", hMidiIn
, lpMidiInHdr
, uSize
);
1480 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
1481 return MMSYSERR_INVALHANDLE
;
1483 return MMDRV_Message(wmld
, MIDM_ADDBUFFER
, (DWORD
)lpMidiInHdr
, uSize
, TRUE
);
1486 /**************************************************************************
1487 * midiInStart [WINMM.@]
1489 UINT WINAPI
midiInStart(HMIDIIN hMidiIn
)
1493 TRACE("(%p)\n", hMidiIn
);
1495 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
1496 return MMSYSERR_INVALHANDLE
;
1498 return MMDRV_Message(wmld
, MIDM_START
, 0L, 0L, TRUE
);
1501 /**************************************************************************
1502 * midiInStop [WINMM.@]
1504 UINT WINAPI
midiInStop(HMIDIIN hMidiIn
)
1508 TRACE("(%p)\n", hMidiIn
);
1510 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
1511 return MMSYSERR_INVALHANDLE
;
1513 return MMDRV_Message(wmld
, MIDM_STOP
, 0L, 0L, TRUE
);
1516 /**************************************************************************
1517 * midiInReset [WINMM.@]
1519 UINT WINAPI
midiInReset(HMIDIIN hMidiIn
)
1523 TRACE("(%p)\n", hMidiIn
);
1525 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
1526 return MMSYSERR_INVALHANDLE
;
1528 return MMDRV_Message(wmld
, MIDM_RESET
, 0L, 0L, TRUE
);
1531 /**************************************************************************
1532 * midiInGetID [WINMM.@]
1534 UINT WINAPI
midiInGetID(HMIDIIN hMidiIn
, UINT
* lpuDeviceID
)
1538 TRACE("(%p, %p)\n", hMidiIn
, lpuDeviceID
);
1540 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
1542 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, TRUE
)) == NULL
)
1543 return MMSYSERR_INVALHANDLE
;
1545 *lpuDeviceID
= wmld
->uDeviceID
;
1547 return MMSYSERR_NOERROR
;
1550 /**************************************************************************
1551 * midiInMessage [WINMM.@]
1553 UINT WINAPI
midiInMessage(HMIDIIN hMidiIn
, UINT uMessage
,
1554 DWORD dwParam1
, DWORD dwParam2
)
1558 TRACE("(%p, %04X, %08lX, %08lX)\n", hMidiIn
, uMessage
, dwParam1
, dwParam2
);
1560 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
1561 return MMSYSERR_INVALHANDLE
;
1566 FIXME("can't handle OPEN or CLOSE message!\n");
1567 return MMSYSERR_NOTSUPPORTED
;
1569 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
1572 typedef struct WINE_MIDIStream
{
1583 LPMIDIHDR lpMidiHdr
;
1586 #define WINE_MSM_HEADER (WM_USER+0)
1587 #define WINE_MSM_STOP (WM_USER+1)
1589 /**************************************************************************
1590 * MMSYSTEM_GetMidiStream [internal]
1592 static BOOL
MMSYSTEM_GetMidiStream(HMIDISTRM hMidiStrm
, WINE_MIDIStream
** lpMidiStrm
, WINE_MIDI
** lplpwm
)
1594 WINE_MIDI
* lpwm
= (LPWINE_MIDI
)MMDRV_Get(hMidiStrm
, MMDRV_MIDIOUT
, FALSE
);
1603 *lpMidiStrm
= (WINE_MIDIStream
*)lpwm
->mod
.rgIds
.dwStreamID
;
1605 return *lpMidiStrm
!= NULL
;
1608 /**************************************************************************
1609 * MMSYSTEM_MidiStream_Convert [internal]
1611 static DWORD
MMSYSTEM_MidiStream_Convert(WINE_MIDIStream
* lpMidiStrm
, DWORD pulse
)
1615 if (lpMidiStrm
->dwTimeDiv
== 0) {
1616 FIXME("Shouldn't happen. lpMidiStrm->dwTimeDiv = 0\n");
1617 } else if (lpMidiStrm
->dwTimeDiv
> 0x8000) { /* SMPTE, unchecked FIXME? */
1618 int nf
= -(char)HIBYTE(lpMidiStrm
->dwTimeDiv
); /* number of frames */
1619 int nsf
= LOBYTE(lpMidiStrm
->dwTimeDiv
); /* number of sub-frames */
1620 ret
= (pulse
* 1000) / (nf
* nsf
);
1622 ret
= (DWORD
)((double)pulse
* ((double)lpMidiStrm
->dwTempo
/ 1000) /
1623 (double)lpMidiStrm
->dwTimeDiv
);
1629 /**************************************************************************
1630 * MMSYSTEM_MidiStream_MessageHandler [internal]
1632 static BOOL
MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream
* lpMidiStrm
, LPWINE_MIDI lpwm
, LPMSG msg
)
1634 LPMIDIHDR lpMidiHdr
;
1638 switch (msg
->message
) {
1640 SetEvent(lpMidiStrm
->hEvent
);
1644 /* this is not quite what MS doc says... */
1645 midiOutReset(lpMidiStrm
->hDevice
);
1646 /* empty list of already submitted buffers */
1647 for (lpMidiHdr
= lpMidiStrm
->lpMidiHdr
; lpMidiHdr
; lpMidiHdr
= (LPMIDIHDR
)lpMidiHdr
->lpNext
) {
1648 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
1649 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
1651 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
,
1652 (HDRVR
)lpMidiStrm
->hDevice
, MM_MOM_DONE
,
1653 lpwm
->mod
.dwInstance
, (DWORD
)lpMidiHdr
, 0L);
1655 lpMidiStrm
->lpMidiHdr
= 0;
1656 SetEvent(lpMidiStrm
->hEvent
);
1658 case WINE_MSM_HEADER
:
1659 /* sets initial tick count for first MIDIHDR */
1660 if (!lpMidiStrm
->dwStartTicks
)
1661 lpMidiStrm
->dwStartTicks
= GetTickCount();
1663 /* FIXME(EPP): "I don't understand the content of the first MIDIHDR sent
1664 * by native mcimidi, it doesn't look like a correct one".
1665 * this trick allows to throw it away... but I don't like it.
1666 * It looks like part of the file I'm trying to play and definitively looks
1667 * like raw midi content
1668 * I'd really like to understand why native mcimidi sends it. Perhaps a bad
1669 * synchronization issue where native mcimidi is still processing raw MIDI
1670 * content before generating MIDIEVENTs ?
1672 * 4c 04 89 3b 00 81 7c 99 3b 43 00 99 23 5e 04 89 L..;..|.;C..#^..
1673 * 3b 00 00 89 23 00 7c 99 3b 45 00 99 28 62 04 89 ;...#.|.;E..(b..
1674 * 3b 00 00 89 28 00 81 7c 99 3b 4e 00 99 23 5e 04 ;...(..|.;N..#^.
1675 * 89 3b 00 00 89 23 00 7c 99 3b 45 00 99 23 78 04 .;...#.|.;E..#x.
1676 * 89 3b 00 00 89 23 00 81 7c 99 3b 48 00 99 23 5e .;...#..|.;H..#^
1677 * 04 89 3b 00 00 89 23 00 7c 99 3b 4e 00 99 28 62 ..;...#.|.;N..(b
1678 * 04 89 3b 00 00 89 28 00 81 7c 99 39 4c 00 99 23 ..;...(..|.9L..#
1679 * 5e 04 89 39 00 00 89 23 00 82 7c 99 3b 4c 00 99 ^..9...#..|.;L..
1680 * 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b 48 00 99 #^..;...#.|.;H..
1681 * 28 62 04 89 3b 00 00 89 28 00 81 7c 99 3b 3f 04 (b..;...(..|.;?.
1682 * 89 3b 00 1c 99 23 5e 04 89 23 00 5c 99 3b 45 00 .;...#^..#.\.;E.
1683 * 99 23 78 04 89 3b 00 00 89 23 00 81 7c 99 3b 46 .#x..;...#..|.;F
1684 * 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b 48 ..#^..;...#.|.;H
1685 * 00 99 28 62 04 89 3b 00 00 89 28 00 81 7c 99 3b ..(b..;...(..|.;
1686 * 46 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b F..#^..;...#.|.;
1687 * 48 00 99 23 78 04 89 3b 00 00 89 23 00 81 7c 99 H..#x..;...#..|.
1688 * 3b 4c 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 ;L..#^..;...#.|.
1690 lpMidiHdr
= (LPMIDIHDR
)msg
->lParam
;
1691 lpData
= lpMidiHdr
->lpData
;
1692 TRACE("Adding %s lpMidiHdr=%p [lpData=0x%08lx dwBufferLength=%lu/%lu dwFlags=0x%08lx size=%u]\n",
1693 (lpMidiHdr
->dwFlags
& MHDR_ISSTRM
) ? "stream" : "regular", lpMidiHdr
,
1694 (DWORD
)lpMidiHdr
, lpMidiHdr
->dwBufferLength
, lpMidiHdr
->dwBytesRecorded
,
1695 lpMidiHdr
->dwFlags
, msg
->wParam
);
1697 /* dumps content of lpMidiHdr->lpData
1698 * FIXME: there should be a debug routine somewhere that already does this
1699 * I hate spreading this type of shit all around the code
1701 for (dwToGo
= 0; dwToGo
< lpMidiHdr
->dwBufferLength
; dwToGo
+= 16) {
1705 for (i
= 0; i
< min(16, lpMidiHdr
->dwBufferLength
- dwToGo
); i
++)
1706 printf("%02x ", lpData
[dwToGo
+ i
]);
1709 for (i
= 0; i
< min(16, lpMidiHdr
->dwBufferLength
- dwToGo
); i
++) {
1710 ch
= lpData
[dwToGo
+ i
];
1711 printf("%c", (ch
>= 0x20 && ch
<= 0x7F) ? ch
: '.');
1716 if (((LPMIDIEVENT
)lpData
)->dwStreamID
!= 0 &&
1717 ((LPMIDIEVENT
)lpData
)->dwStreamID
!= 0xFFFFFFFF &&
1718 ((LPMIDIEVENT
)lpData
)->dwStreamID
!= (DWORD
)lpMidiStrm
) {
1719 FIXME("Dropping bad %s lpMidiHdr (streamID=%08lx)\n",
1720 (lpMidiHdr
->dwFlags
& MHDR_ISSTRM
) ? "stream" : "regular",
1721 ((LPMIDIEVENT
)lpData
)->dwStreamID
);
1722 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
1723 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
1725 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
,
1726 (HDRVR
)lpMidiStrm
->hDevice
, MM_MOM_DONE
,
1727 lpwm
->mod
.dwInstance
, (DWORD
)lpMidiHdr
, 0L);
1731 for (lpmh
= &lpMidiStrm
->lpMidiHdr
; *lpmh
; lpmh
= (LPMIDIHDR
*)&((*lpmh
)->lpNext
));
1733 lpMidiHdr
= (LPMIDIHDR
)msg
->lParam
;
1734 lpMidiHdr
->lpNext
= 0;
1735 lpMidiHdr
->dwFlags
|= MHDR_INQUEUE
;
1736 lpMidiHdr
->dwFlags
&= MHDR_DONE
;
1737 lpMidiHdr
->dwOffset
= 0;
1741 FIXME("Unknown message %d\n", msg
->message
);
1747 /**************************************************************************
1748 * MMSYSTEM_MidiStream_Player [internal]
1750 static DWORD CALLBACK
MMSYSTEM_MidiStream_Player(LPVOID pmt
)
1752 WINE_MIDIStream
* lpMidiStrm
= pmt
;
1757 LPMIDIHDR lpMidiHdr
;
1761 TRACE("(%p)!\n", lpMidiStrm
);
1764 (lpwm
= (LPWINE_MIDI
)MMDRV_Get(lpMidiStrm
->hDevice
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
1767 /* force thread's queue creation */
1768 /* Used to be InitThreadInput16(0, 5); */
1769 /* but following works also with hack in midiStreamOpen */
1770 PeekMessageA(&msg
, 0, 0, 0, 0);
1772 /* FIXME: this next line must be called before midiStreamOut or midiStreamRestart are called */
1773 SetEvent(lpMidiStrm
->hEvent
);
1774 TRACE("Ready to go 1\n");
1775 /* thread is started in paused mode */
1776 SuspendThread(lpMidiStrm
->hThread
);
1777 TRACE("Ready to go 2\n");
1779 lpMidiStrm
->dwStartTicks
= 0;
1780 lpMidiStrm
->dwPulses
= 0;
1782 lpMidiStrm
->lpMidiHdr
= 0;
1785 lpMidiHdr
= lpMidiStrm
->lpMidiHdr
;
1787 /* for first message, block until one arrives, then process all that are available */
1788 GetMessageA(&msg
, 0, 0, 0);
1790 if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm
, lpwm
, &msg
))
1792 } while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
));
1798 lpData
= lpMidiHdr
->lpData
;
1800 me
= (LPMIDIEVENT
)(lpData
+ lpMidiHdr
->dwOffset
);
1802 /* do we have to wait ? */
1803 if (me
->dwDeltaTime
) {
1804 lpMidiStrm
->dwPositionMS
+= MMSYSTEM_MidiStream_Convert(lpMidiStrm
, me
->dwDeltaTime
);
1805 lpMidiStrm
->dwPulses
+= me
->dwDeltaTime
;
1807 dwToGo
= lpMidiStrm
->dwStartTicks
+ lpMidiStrm
->dwPositionMS
;
1809 TRACE("%ld/%ld/%ld\n", dwToGo
, GetTickCount(), me
->dwDeltaTime
);
1810 while ((dwCurrTC
= GetTickCount()) < dwToGo
) {
1811 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, dwToGo
- dwCurrTC
, QS_ALLINPUT
) == WAIT_OBJECT_0
) {
1812 /* got a message, handle it */
1813 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) {
1814 if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm
, lpwm
, &msg
))
1819 /* timeout, so me->dwDeltaTime is elapsed, can break the while loop */
1824 switch (MEVT_EVENTTYPE(me
->dwEvent
& ~MEVT_F_CALLBACK
)) {
1826 FIXME("NIY: MEVT_COMMENT\n");
1827 /* do nothing, skip bytes */
1830 FIXME("NIY: MEVT_LONGMSG, aka sending Sysex event\n");
1835 midiOutShortMsg(lpMidiStrm
->hDevice
, MEVT_EVENTPARM(me
->dwEvent
));
1838 lpMidiStrm
->dwTempo
= MEVT_EVENTPARM(me
->dwEvent
);
1843 FIXME("Unknown MEVT (0x%02x)\n", MEVT_EVENTTYPE(me
->dwEvent
& ~MEVT_F_CALLBACK
));
1846 if (me
->dwEvent
& MEVT_F_CALLBACK
) {
1847 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
,
1848 (HDRVR
)lpMidiStrm
->hDevice
, MM_MOM_POSITIONCB
,
1849 lpwm
->mod
.dwInstance
, (LPARAM
)lpMidiHdr
, 0L);
1851 lpMidiHdr
->dwOffset
+= sizeof(MIDIEVENT
) - sizeof(me
->dwParms
);
1852 if (me
->dwEvent
& MEVT_F_LONG
)
1853 lpMidiHdr
->dwOffset
+= (MEVT_EVENTPARM(me
->dwEvent
) + 3) & ~3;
1854 if (lpMidiHdr
->dwOffset
>= lpMidiHdr
->dwBufferLength
) {
1855 /* done with this header */
1856 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
1857 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
1859 lpMidiStrm
->lpMidiHdr
= (LPMIDIHDR
)lpMidiHdr
->lpNext
;
1860 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
,
1861 (HDRVR
)lpMidiStrm
->hDevice
, MM_MOM_DONE
,
1862 lpwm
->mod
.dwInstance
, (DWORD
)lpMidiHdr
, 0L);
1867 TRACE("End of thread\n");
1869 return 0; /* for removing the warning, never executed */
1872 /**************************************************************************
1873 * MMSYSTEM_MidiStream_PostMessage [internal]
1875 static BOOL
MMSYSTEM_MidiStream_PostMessage(WINE_MIDIStream
* lpMidiStrm
, WORD msg
, DWORD pmt1
, DWORD pmt2
)
1877 if (PostThreadMessageA(lpMidiStrm
->dwThreadID
, msg
, pmt1
, pmt2
)) {
1880 ReleaseThunkLock(&count
);
1881 WaitForSingleObject(lpMidiStrm
->hEvent
, INFINITE
);
1882 RestoreThunkLock(count
);
1884 WARN("bad PostThreadMessageA\n");
1890 /**************************************************************************
1891 * midiStreamClose [WINMM.@]
1893 MMRESULT WINAPI
midiStreamClose(HMIDISTRM hMidiStrm
)
1895 WINE_MIDIStream
* lpMidiStrm
;
1897 TRACE("(%p)!\n", hMidiStrm
);
1899 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
))
1900 return MMSYSERR_INVALHANDLE
;
1902 midiStreamStop(hMidiStrm
);
1903 MMSYSTEM_MidiStream_PostMessage(lpMidiStrm
, WM_QUIT
, 0, 0);
1904 HeapFree(GetProcessHeap(), 0, lpMidiStrm
);
1905 CloseHandle(lpMidiStrm
->hEvent
);
1907 return midiOutClose((HMIDIOUT
)hMidiStrm
);
1910 /**************************************************************************
1911 * MMSYSTEM_MidiStream_Open [internal]
1913 MMRESULT
MIDI_StreamOpen(HMIDISTRM
* lphMidiStrm
, LPUINT lpuDeviceID
, DWORD cMidi
,
1914 DWORD dwCallback
, DWORD dwInstance
, DWORD fdwOpen
,
1917 WINE_MIDIStream
* lpMidiStrm
;
1919 MIDIOPENSTRMID mosm
;
1923 TRACE("(%p, %p, %ld, 0x%08lx, 0x%08lx, 0x%08lx)!\n",
1924 lphMidiStrm
, lpuDeviceID
, cMidi
, dwCallback
, dwInstance
, fdwOpen
);
1926 if (cMidi
!= 1 || lphMidiStrm
== NULL
|| lpuDeviceID
== NULL
)
1927 return MMSYSERR_INVALPARAM
;
1929 lpMidiStrm
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_MIDIStream
));
1931 return MMSYSERR_NOMEM
;
1933 lpMidiStrm
->dwTempo
= 500000;
1934 lpMidiStrm
->dwTimeDiv
= 480; /* 480 is 120 quater notes per minute *//* FIXME ??*/
1935 lpMidiStrm
->dwPositionMS
= 0;
1937 mosm
.dwStreamID
= (DWORD
)lpMidiStrm
;
1938 /* FIXME: the correct value is not allocated yet for MAPPER */
1939 mosm
.wDeviceID
= *lpuDeviceID
;
1940 lpwm
= MIDI_OutAlloc(&hMidiOut
, &dwCallback
, &dwInstance
, &fdwOpen
, 1, &mosm
, bFrom32
);
1941 lpMidiStrm
->hDevice
= hMidiOut
;
1943 *lphMidiStrm
= (HMIDISTRM
)hMidiOut
;
1945 /* FIXME: is lpuDevice initialized upon entering midiStreamOpen ? */
1946 FIXME("*lpuDeviceID=%x\n", *lpuDeviceID
);
1947 lpwm
->mld
.uDeviceID
= *lpuDeviceID
= 0;
1949 ret
= MMDRV_Open(&lpwm
->mld
, MODM_OPEN
, (DWORD
)&lpwm
->mod
, fdwOpen
);
1950 lpMidiStrm
->hEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1951 lpMidiStrm
->wFlags
= HIWORD(fdwOpen
);
1953 lpMidiStrm
->hThread
= CreateThread(NULL
, 0, MMSYSTEM_MidiStream_Player
,
1954 lpMidiStrm
, 0, &(lpMidiStrm
->dwThreadID
));
1956 if (!lpMidiStrm
->hThread
) {
1957 midiStreamClose((HMIDISTRM
)hMidiOut
);
1958 return MMSYSERR_NOMEM
;
1961 /* wait for thread to have started, and for its queue to be created */
1965 /* (Release|Restore)ThunkLock() is needed when this method is called from 16 bit code,
1966 * (meaning the Win16Lock is set), so that it's released and the 32 bit thread running
1967 * MMSYSTEM_MidiStreamPlayer can acquire Win16Lock to create its queue.
1969 ReleaseThunkLock(&count
);
1970 WaitForSingleObject(lpMidiStrm
->hEvent
, INFINITE
);
1971 RestoreThunkLock(count
);
1974 TRACE("=> (%u/%d) hMidi=%p ret=%d lpMidiStrm=%p\n",
1975 *lpuDeviceID
, lpwm
->mld
.uDeviceID
, *lphMidiStrm
, ret
, lpMidiStrm
);
1979 /**************************************************************************
1980 * midiStreamOpen [WINMM.@]
1982 MMRESULT WINAPI
midiStreamOpen(HMIDISTRM
* lphMidiStrm
, LPUINT lpuDeviceID
,
1983 DWORD cMidi
, DWORD dwCallback
,
1984 DWORD dwInstance
, DWORD fdwOpen
)
1986 return MIDI_StreamOpen(lphMidiStrm
, lpuDeviceID
, cMidi
, dwCallback
,
1987 dwInstance
, fdwOpen
, TRUE
);
1990 /**************************************************************************
1991 * midiStreamOut [WINMM.@]
1993 MMRESULT WINAPI
midiStreamOut(HMIDISTRM hMidiStrm
, LPMIDIHDR lpMidiHdr
,
1996 WINE_MIDIStream
* lpMidiStrm
;
1997 DWORD ret
= MMSYSERR_NOERROR
;
1999 TRACE("(%p, %p, %u)!\n", hMidiStrm
, lpMidiHdr
, cbMidiHdr
);
2001 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
2002 ret
= MMSYSERR_INVALHANDLE
;
2003 } else if (!lpMidiHdr
) {
2004 ret
= MMSYSERR_INVALPARAM
;
2006 if (!PostThreadMessageA(lpMidiStrm
->dwThreadID
,
2007 WINE_MSM_HEADER
, cbMidiHdr
,
2008 (DWORD
)lpMidiHdr
)) {
2009 WARN("bad PostThreadMessageA\n");
2010 ret
= MMSYSERR_ERROR
;
2016 /**************************************************************************
2017 * midiStreamPause [WINMM.@]
2019 MMRESULT WINAPI
midiStreamPause(HMIDISTRM hMidiStrm
)
2021 WINE_MIDIStream
* lpMidiStrm
;
2022 DWORD ret
= MMSYSERR_NOERROR
;
2024 TRACE("(%p)!\n", hMidiStrm
);
2026 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
2027 ret
= MMSYSERR_INVALHANDLE
;
2029 if (SuspendThread(lpMidiStrm
->hThread
) == 0xFFFFFFFF) {
2030 WARN("bad Suspend (%ld)\n", GetLastError());
2031 ret
= MMSYSERR_ERROR
;
2037 /**************************************************************************
2038 * midiStreamPosition [WINMM.@]
2040 MMRESULT WINAPI
midiStreamPosition(HMIDISTRM hMidiStrm
, LPMMTIME lpMMT
, UINT cbmmt
)
2042 WINE_MIDIStream
* lpMidiStrm
;
2043 DWORD ret
= MMSYSERR_NOERROR
;
2045 TRACE("(%p, %p, %u)!\n", hMidiStrm
, lpMMT
, cbmmt
);
2047 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
2048 ret
= MMSYSERR_INVALHANDLE
;
2049 } else if (lpMMT
== NULL
|| cbmmt
!= sizeof(MMTIME
)) {
2050 ret
= MMSYSERR_INVALPARAM
;
2052 switch (lpMMT
->wType
) {
2054 lpMMT
->u
.ms
= lpMidiStrm
->dwPositionMS
;
2055 TRACE("=> %ld ms\n", lpMMT
->u
.ms
);
2058 lpMMT
->u
.ticks
= lpMidiStrm
->dwPulses
;
2059 TRACE("=> %ld ticks\n", lpMMT
->u
.ticks
);
2062 WARN("Unsupported time type %d\n", lpMMT
->wType
);
2063 lpMMT
->wType
= TIME_MS
;
2064 ret
= MMSYSERR_INVALPARAM
;
2071 /**************************************************************************
2072 * midiStreamProperty [WINMM.@]
2074 MMRESULT WINAPI
midiStreamProperty(HMIDISTRM hMidiStrm
, LPBYTE lpPropData
, DWORD dwProperty
)
2076 WINE_MIDIStream
* lpMidiStrm
;
2077 MMRESULT ret
= MMSYSERR_NOERROR
;
2079 TRACE("(%p, %p, %lx)\n", hMidiStrm
, lpPropData
, dwProperty
);
2081 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
2082 ret
= MMSYSERR_INVALHANDLE
;
2083 } else if ((dwProperty
& (MIDIPROP_GET
|MIDIPROP_SET
)) == 0) {
2084 ret
= MMSYSERR_INVALPARAM
;
2085 } else if (dwProperty
& MIDIPROP_TEMPO
) {
2086 MIDIPROPTEMPO
* mpt
= (MIDIPROPTEMPO
*)lpPropData
;
2088 if (sizeof(MIDIPROPTEMPO
) != mpt
->cbStruct
) {
2089 ret
= MMSYSERR_INVALPARAM
;
2090 } else if (dwProperty
& MIDIPROP_SET
) {
2091 lpMidiStrm
->dwTempo
= mpt
->dwTempo
;
2092 TRACE("Setting tempo to %ld\n", mpt
->dwTempo
);
2093 } else if (dwProperty
& MIDIPROP_GET
) {
2094 mpt
->dwTempo
= lpMidiStrm
->dwTempo
;
2095 TRACE("Getting tempo <= %ld\n", mpt
->dwTempo
);
2097 } else if (dwProperty
& MIDIPROP_TIMEDIV
) {
2098 MIDIPROPTIMEDIV
* mptd
= (MIDIPROPTIMEDIV
*)lpPropData
;
2100 if (sizeof(MIDIPROPTIMEDIV
) != mptd
->cbStruct
) {
2101 ret
= MMSYSERR_INVALPARAM
;
2102 } else if (dwProperty
& MIDIPROP_SET
) {
2103 lpMidiStrm
->dwTimeDiv
= mptd
->dwTimeDiv
;
2104 TRACE("Setting time div to %ld\n", mptd
->dwTimeDiv
);
2105 } else if (dwProperty
& MIDIPROP_GET
) {
2106 mptd
->dwTimeDiv
= lpMidiStrm
->dwTimeDiv
;
2107 TRACE("Getting time div <= %ld\n", mptd
->dwTimeDiv
);
2110 ret
= MMSYSERR_INVALPARAM
;
2116 /**************************************************************************
2117 * midiStreamRestart [WINMM.@]
2119 MMRESULT WINAPI
midiStreamRestart(HMIDISTRM hMidiStrm
)
2121 WINE_MIDIStream
* lpMidiStrm
;
2122 MMRESULT ret
= MMSYSERR_NOERROR
;
2124 TRACE("(%p)!\n", hMidiStrm
);
2126 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
2127 ret
= MMSYSERR_INVALHANDLE
;
2131 /* since we increase the thread suspend count on each midiStreamPause
2132 * there may be a need for several midiStreamResume
2135 ret
= ResumeThread(lpMidiStrm
->hThread
);
2136 } while (ret
!= 0xFFFFFFFF && ret
!= 0);
2137 if (ret
== 0xFFFFFFFF) {
2138 WARN("bad Resume (%ld)\n", GetLastError());
2139 ret
= MMSYSERR_ERROR
;
2141 lpMidiStrm
->dwStartTicks
= GetTickCount() - lpMidiStrm
->dwPositionMS
;
2147 /**************************************************************************
2148 * midiStreamStop [WINMM.@]
2150 MMRESULT WINAPI
midiStreamStop(HMIDISTRM hMidiStrm
)
2152 WINE_MIDIStream
* lpMidiStrm
;
2153 MMRESULT ret
= MMSYSERR_NOERROR
;
2155 TRACE("(%p)!\n", hMidiStrm
);
2157 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
2158 ret
= MMSYSERR_INVALHANDLE
;
2160 /* in case stream has been paused... FIXME is the current state correct ? */
2161 midiStreamRestart(hMidiStrm
);
2162 MMSYSTEM_MidiStream_PostMessage(lpMidiStrm
, WINE_MSM_STOP
, 0, 0);
2167 UINT
WAVE_Open(HANDLE
* lphndl
, UINT uDeviceID
, UINT uType
,
2168 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
2169 DWORD dwInstance
, DWORD dwFlags
, BOOL bFrom32
)
2173 DWORD dwRet
= MMSYSERR_NOERROR
;
2176 TRACE("(%p, %d, %s, %p, %08lX, %08lX, %08lX, %d);\n",
2177 lphndl
, (int)uDeviceID
, (uType
==MMDRV_WAVEOUT
)?"Out":"In", lpFormat
, dwCallback
,
2178 dwInstance
, dwFlags
, bFrom32
?32:16);
2180 if (dwFlags
& WAVE_FORMAT_QUERY
) TRACE("WAVE_FORMAT_QUERY requested !\n");
2182 if (lpFormat
== NULL
) return WAVERR_BADFORMAT
;
2183 if ((dwFlags
& WAVE_MAPPED
) && (uDeviceID
== (UINT
)-1))
2184 return MMSYSERR_INVALPARAM
;
2186 TRACE("wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u\n",
2187 lpFormat
->wFormatTag
, lpFormat
->nChannels
, lpFormat
->nSamplesPerSec
,
2188 lpFormat
->nAvgBytesPerSec
, lpFormat
->nBlockAlign
, lpFormat
->wBitsPerSample
, lpFormat
->cbSize
);
2190 if ((wmld
= MMDRV_Alloc(sizeof(WINE_WAVE
), uType
, &handle
,
2191 &dwFlags
, &dwCallback
, &dwInstance
, bFrom32
)) == NULL
)
2192 return MMSYSERR_NOMEM
;
2195 wod
.lpFormat
= lpFormat
; /* should the struct be copied iso pointer? */
2196 wod
.dwCallback
= dwCallback
;
2197 wod
.dwInstance
= dwInstance
;
2200 TRACE("cb=%08lx\n", wod
.dwCallback
);
2203 if (dwFlags
& WAVE_MAPPED
) {
2204 wod
.uMappedDeviceID
= uDeviceID
;
2205 uDeviceID
= WAVE_MAPPER
;
2207 wod
.uMappedDeviceID
= -1;
2209 wmld
->uDeviceID
= uDeviceID
;
2211 dwRet
= MMDRV_Open(wmld
, (uType
== MMDRV_WAVEOUT
) ? WODM_OPEN
: WIDM_OPEN
,
2212 (DWORD
)&wod
, dwFlags
);
2214 if (dwRet
!= WAVERR_BADFORMAT
||
2215 (dwFlags
& (WAVE_MAPPED
|WAVE_FORMAT_DIRECT
)) != 0) break;
2216 /* if we ask for a format which isn't supported by the physical driver,
2217 * let's try to map it through the wave mapper (except, if we already tried
2218 * or user didn't allow us to use acm codecs)
2220 dwFlags
|= WAVE_MAPPED
;
2221 /* we shall loop only one */
2224 if ((dwFlags
& WAVE_FORMAT_QUERY
) || dwRet
!= MMSYSERR_NOERROR
) {
2225 MMDRV_Free(handle
, wmld
);
2229 if (lphndl
!= NULL
) *lphndl
= handle
;
2230 TRACE("=> %ld hWave=%p\n", dwRet
, handle
);
2235 /**************************************************************************
2236 * waveOutGetNumDevs [WINMM.@]
2238 UINT WINAPI
waveOutGetNumDevs(void)
2240 return MMDRV_GetNum(MMDRV_WAVEOUT
);
2243 /**************************************************************************
2244 * waveOutGetDevCapsA [WINMM.@]
2246 UINT WINAPI
waveOutGetDevCapsA(UINT uDeviceID
, LPWAVEOUTCAPSA lpCaps
,
2251 TRACE("(%u %p %u)!\n", uDeviceID
, lpCaps
, uSize
);
2253 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
2255 if ((wmld
= MMDRV_Get((HANDLE
)uDeviceID
, MMDRV_WAVEOUT
, TRUE
)) == NULL
)
2256 return MMSYSERR_BADDEVICEID
;
2258 return MMDRV_Message(wmld
, WODM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
2262 /**************************************************************************
2263 * waveOutGetDevCapsW [WINMM.@]
2265 UINT WINAPI
waveOutGetDevCapsW(UINT uDeviceID
, LPWAVEOUTCAPSW lpCaps
,
2271 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
2273 ret
= waveOutGetDevCapsA(uDeviceID
, &wocA
, sizeof(wocA
));
2275 if (ret
== MMSYSERR_NOERROR
) {
2276 lpCaps
->wMid
= wocA
.wMid
;
2277 lpCaps
->wPid
= wocA
.wPid
;
2278 lpCaps
->vDriverVersion
= wocA
.vDriverVersion
;
2279 MultiByteToWideChar( CP_ACP
, 0, wocA
.szPname
, -1, lpCaps
->szPname
,
2280 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
2281 lpCaps
->dwFormats
= wocA
.dwFormats
;
2282 lpCaps
->wChannels
= wocA
.wChannels
;
2283 lpCaps
->dwSupport
= wocA
.dwSupport
;
2288 /**************************************************************************
2289 * WAVE_GetErrorText [internal]
2291 static UINT16
WAVE_GetErrorText(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
2293 UINT16 ret
= MMSYSERR_BADERRNUM
;
2295 if (lpText
== NULL
) {
2296 ret
= MMSYSERR_INVALPARAM
;
2297 } else if (uSize
== 0) {
2298 ret
= MMSYSERR_NOERROR
;
2300 /* test has been removed 'coz MMSYSERR_BASE is 0, and gcc did emit
2301 * a warning for the test was always true */
2302 (/*uError >= MMSYSERR_BASE && */uError
<= MMSYSERR_LASTERROR
) ||
2303 (uError
>= WAVERR_BASE
&& uError
<= WAVERR_LASTERROR
)) {
2305 if (LoadStringA(WINMM_IData
->hWinMM32Instance
,
2306 uError
, lpText
, uSize
) > 0) {
2307 ret
= MMSYSERR_NOERROR
;
2313 /**************************************************************************
2314 * waveOutGetErrorTextA [WINMM.@]
2316 UINT WINAPI
waveOutGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
2318 return WAVE_GetErrorText(uError
, lpText
, uSize
);
2321 /**************************************************************************
2322 * waveOutGetErrorTextW [WINMM.@]
2324 UINT WINAPI
waveOutGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
2326 LPSTR xstr
= HeapAlloc(GetProcessHeap(), 0, uSize
);
2327 UINT ret
= WAVE_GetErrorText(uError
, xstr
, uSize
);
2329 MultiByteToWideChar( CP_ACP
, 0, xstr
, -1, lpText
, uSize
);
2330 HeapFree(GetProcessHeap(), 0, xstr
);
2334 /**************************************************************************
2335 * waveOutOpen [WINMM.@]
2336 * All the args/structs have the same layout as the win16 equivalents
2338 UINT WINAPI
waveOutOpen(HWAVEOUT
* lphWaveOut
, UINT uDeviceID
,
2339 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
2340 DWORD dwInstance
, DWORD dwFlags
)
2342 return WAVE_Open((HANDLE
*)lphWaveOut
, uDeviceID
, MMDRV_WAVEOUT
, lpFormat
,
2343 dwCallback
, dwInstance
, dwFlags
, TRUE
);
2346 /**************************************************************************
2347 * waveOutClose [WINMM.@]
2349 UINT WINAPI
waveOutClose(HWAVEOUT hWaveOut
)
2354 TRACE("(%p)\n", hWaveOut
);
2356 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2357 return MMSYSERR_INVALHANDLE
;
2359 dwRet
= MMDRV_Close(wmld
, WODM_CLOSE
);
2360 MMDRV_Free(hWaveOut
, wmld
);
2365 /**************************************************************************
2366 * waveOutPrepareHeader [WINMM.@]
2368 UINT WINAPI
waveOutPrepareHeader(HWAVEOUT hWaveOut
,
2369 WAVEHDR
* lpWaveOutHdr
, UINT uSize
)
2373 TRACE("(%p, %p, %u);\n", hWaveOut
, lpWaveOutHdr
, uSize
);
2375 if (lpWaveOutHdr
== NULL
) return MMSYSERR_INVALPARAM
;
2377 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2378 return MMSYSERR_INVALHANDLE
;
2380 return MMDRV_Message(wmld
, WODM_PREPARE
, (DWORD
)lpWaveOutHdr
, uSize
, TRUE
);
2383 /**************************************************************************
2384 * waveOutUnprepareHeader [WINMM.@]
2386 UINT WINAPI
waveOutUnprepareHeader(HWAVEOUT hWaveOut
,
2387 LPWAVEHDR lpWaveOutHdr
, UINT uSize
)
2391 TRACE("(%p, %p, %u);\n", hWaveOut
, lpWaveOutHdr
, uSize
);
2393 if (!(lpWaveOutHdr
->dwFlags
& WHDR_PREPARED
)) {
2394 return MMSYSERR_NOERROR
;
2397 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2398 return MMSYSERR_INVALHANDLE
;
2400 return MMDRV_Message(wmld
, WODM_UNPREPARE
, (DWORD
)lpWaveOutHdr
, uSize
, TRUE
);
2403 /**************************************************************************
2404 * waveOutWrite [WINMM.@]
2406 UINT WINAPI
waveOutWrite(HWAVEOUT hWaveOut
, LPWAVEHDR lpWaveOutHdr
,
2411 TRACE("(%p, %p, %u);\n", hWaveOut
, lpWaveOutHdr
, uSize
);
2413 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2414 return MMSYSERR_INVALHANDLE
;
2416 return MMDRV_Message(wmld
, WODM_WRITE
, (DWORD
)lpWaveOutHdr
, uSize
, TRUE
);
2419 /**************************************************************************
2420 * waveOutBreakLoop [WINMM.@]
2422 UINT WINAPI
waveOutBreakLoop(HWAVEOUT hWaveOut
)
2426 TRACE("(%p);\n", hWaveOut
);
2428 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2429 return MMSYSERR_INVALHANDLE
;
2430 return MMDRV_Message(wmld
, WODM_BREAKLOOP
, 0L, 0L, TRUE
);
2433 /**************************************************************************
2434 * waveOutPause [WINMM.@]
2436 UINT WINAPI
waveOutPause(HWAVEOUT hWaveOut
)
2440 TRACE("(%p);\n", hWaveOut
);
2442 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2443 return MMSYSERR_INVALHANDLE
;
2444 return MMDRV_Message(wmld
, WODM_PAUSE
, 0L, 0L, TRUE
);
2447 /**************************************************************************
2448 * waveOutReset [WINMM.@]
2450 UINT WINAPI
waveOutReset(HWAVEOUT hWaveOut
)
2454 TRACE("(%p);\n", hWaveOut
);
2456 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2457 return MMSYSERR_INVALHANDLE
;
2458 return MMDRV_Message(wmld
, WODM_RESET
, 0L, 0L, TRUE
);
2461 /**************************************************************************
2462 * waveOutRestart [WINMM.@]
2464 UINT WINAPI
waveOutRestart(HWAVEOUT hWaveOut
)
2468 TRACE("(%p);\n", hWaveOut
);
2470 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2471 return MMSYSERR_INVALHANDLE
;
2472 return MMDRV_Message(wmld
, WODM_RESTART
, 0L, 0L, TRUE
);
2475 /**************************************************************************
2476 * waveOutGetPosition [WINMM.@]
2478 UINT WINAPI
waveOutGetPosition(HWAVEOUT hWaveOut
, LPMMTIME lpTime
,
2483 TRACE("(%p, %p, %u);\n", hWaveOut
, lpTime
, uSize
);
2485 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2486 return MMSYSERR_INVALHANDLE
;
2488 return MMDRV_Message(wmld
, WODM_GETPOS
, (DWORD
)lpTime
, uSize
, TRUE
);
2491 /**************************************************************************
2492 * waveOutGetPitch [WINMM.@]
2494 UINT WINAPI
waveOutGetPitch(HWAVEOUT hWaveOut
, LPDWORD lpdw
)
2498 TRACE("(%p, %08lx);\n", hWaveOut
, (DWORD
)lpdw
);
2500 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2501 return MMSYSERR_INVALHANDLE
;
2502 return MMDRV_Message(wmld
, WODM_GETPITCH
, (DWORD
)lpdw
, 0L, TRUE
);
2505 /**************************************************************************
2506 * waveOutSetPitch [WINMM.@]
2508 UINT WINAPI
waveOutSetPitch(HWAVEOUT hWaveOut
, DWORD dw
)
2512 TRACE("(%p, %08lx);\n", hWaveOut
, (DWORD
)dw
);
2514 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2515 return MMSYSERR_INVALHANDLE
;
2516 return MMDRV_Message(wmld
, WODM_SETPITCH
, dw
, 0L, TRUE
);
2519 /**************************************************************************
2520 * waveOutGetPlaybackRate [WINMM.@]
2522 UINT WINAPI
waveOutGetPlaybackRate(HWAVEOUT hWaveOut
, LPDWORD lpdw
)
2526 TRACE("(%p, %08lx);\n", hWaveOut
, (DWORD
)lpdw
);
2528 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2529 return MMSYSERR_INVALHANDLE
;
2530 return MMDRV_Message(wmld
, WODM_GETPLAYBACKRATE
, (DWORD
)lpdw
, 0L, TRUE
);
2533 /**************************************************************************
2534 * waveOutSetPlaybackRate [WINMM.@]
2536 UINT WINAPI
waveOutSetPlaybackRate(HWAVEOUT hWaveOut
, DWORD dw
)
2540 TRACE("(%p, %08lx);\n", hWaveOut
, (DWORD
)dw
);
2542 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2543 return MMSYSERR_INVALHANDLE
;
2544 return MMDRV_Message(wmld
, WODM_SETPLAYBACKRATE
, dw
, 0L, TRUE
);
2547 /**************************************************************************
2548 * waveOutGetVolume [WINMM.@]
2550 UINT WINAPI
waveOutGetVolume(HWAVEOUT hWaveOut
, LPDWORD lpdw
)
2554 TRACE("(%p, %08lx);\n", hWaveOut
, (DWORD
)lpdw
);
2556 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, TRUE
)) == NULL
)
2557 return MMSYSERR_INVALHANDLE
;
2559 return MMDRV_Message(wmld
, WODM_GETVOLUME
, (DWORD
)lpdw
, 0L, TRUE
);
2562 /**************************************************************************
2563 * waveOutSetVolume [WINMM.@]
2565 UINT WINAPI
waveOutSetVolume(HWAVEOUT hWaveOut
, DWORD dw
)
2569 TRACE("(%p, %08lx);\n", hWaveOut
, dw
);
2571 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, TRUE
)) == NULL
)
2572 return MMSYSERR_INVALHANDLE
;
2574 return MMDRV_Message(wmld
, WODM_SETVOLUME
, dw
, 0L, TRUE
);
2577 /**************************************************************************
2578 * waveOutGetID [WINMM.@]
2580 UINT WINAPI
waveOutGetID(HWAVEOUT hWaveOut
, UINT
* lpuDeviceID
)
2584 TRACE("(%p, %p);\n", hWaveOut
, lpuDeviceID
);
2586 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
2588 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
2589 return MMSYSERR_INVALHANDLE
;
2591 *lpuDeviceID
= wmld
->uDeviceID
;
2595 /**************************************************************************
2596 * waveOutMessage [WINMM.@]
2598 UINT WINAPI
waveOutMessage(HWAVEOUT hWaveOut
, UINT uMessage
,
2599 DWORD dwParam1
, DWORD dwParam2
)
2603 TRACE("(%p, %u, %ld, %ld)\n", hWaveOut
, uMessage
, dwParam1
, dwParam2
);
2605 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
) {
2606 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, TRUE
)) != NULL
) {
2607 return MMDRV_PhysicalFeatures(wmld
, uMessage
, dwParam1
, dwParam2
);
2609 return MMSYSERR_INVALHANDLE
;
2613 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
2614 return MMSYSERR_INVALPARAM
;
2616 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
2619 /**************************************************************************
2620 * waveInGetNumDevs [WINMM.@]
2622 UINT WINAPI
waveInGetNumDevs(void)
2624 return MMDRV_GetNum(MMDRV_WAVEIN
);
2627 /**************************************************************************
2628 * waveInGetDevCapsW [WINMM.@]
2630 UINT WINAPI
waveInGetDevCapsW(UINT uDeviceID
, LPWAVEINCAPSW lpCaps
, UINT uSize
)
2633 UINT ret
= waveInGetDevCapsA(uDeviceID
, &wicA
, uSize
);
2635 if (ret
== MMSYSERR_NOERROR
) {
2636 lpCaps
->wMid
= wicA
.wMid
;
2637 lpCaps
->wPid
= wicA
.wPid
;
2638 lpCaps
->vDriverVersion
= wicA
.vDriverVersion
;
2639 MultiByteToWideChar( CP_ACP
, 0, wicA
.szPname
, -1, lpCaps
->szPname
,
2640 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
2641 lpCaps
->dwFormats
= wicA
.dwFormats
;
2642 lpCaps
->wChannels
= wicA
.wChannels
;
2648 /**************************************************************************
2649 * waveInGetDevCapsA [WINMM.@]
2651 UINT WINAPI
waveInGetDevCapsA(UINT uDeviceID
, LPWAVEINCAPSA lpCaps
, UINT uSize
)
2655 TRACE("(%u %p %u)!\n", uDeviceID
, lpCaps
, uSize
);
2657 if ((wmld
= MMDRV_Get((HANDLE
)uDeviceID
, MMDRV_WAVEIN
, TRUE
)) == NULL
)
2658 return MMSYSERR_BADDEVICEID
;
2660 return MMDRV_Message(wmld
, WIDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
2663 /**************************************************************************
2664 * waveInGetErrorTextA [WINMM.@]
2666 UINT WINAPI
waveInGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
2668 return WAVE_GetErrorText(uError
, lpText
, uSize
);
2671 /**************************************************************************
2672 * waveInGetErrorTextW [WINMM.@]
2674 UINT WINAPI
waveInGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
2676 LPSTR txt
= HeapAlloc(GetProcessHeap(), 0, uSize
);
2677 UINT ret
= WAVE_GetErrorText(uError
, txt
, uSize
);
2679 MultiByteToWideChar( CP_ACP
, 0, txt
, -1, lpText
, uSize
);
2680 HeapFree(GetProcessHeap(), 0, txt
);
2684 /**************************************************************************
2685 * waveInOpen [WINMM.@]
2687 UINT WINAPI
waveInOpen(HWAVEIN
* lphWaveIn
, UINT uDeviceID
,
2688 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
2689 DWORD dwInstance
, DWORD dwFlags
)
2691 return WAVE_Open((HANDLE
*)lphWaveIn
, uDeviceID
, MMDRV_WAVEIN
, lpFormat
,
2692 dwCallback
, dwInstance
, dwFlags
, TRUE
);
2695 /**************************************************************************
2696 * waveInClose [WINMM.@]
2698 UINT WINAPI
waveInClose(HWAVEIN hWaveIn
)
2703 TRACE("(%p)\n", hWaveIn
);
2705 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
2706 return MMSYSERR_INVALHANDLE
;
2708 dwRet
= MMDRV_Message(wmld
, WIDM_CLOSE
, 0L, 0L, TRUE
);
2709 MMDRV_Free(hWaveIn
, wmld
);
2713 /**************************************************************************
2714 * waveInPrepareHeader [WINMM.@]
2716 UINT WINAPI
waveInPrepareHeader(HWAVEIN hWaveIn
, WAVEHDR
* lpWaveInHdr
,
2721 TRACE("(%p, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
2723 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
2724 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
2725 return MMSYSERR_INVALHANDLE
;
2727 lpWaveInHdr
->dwBytesRecorded
= 0;
2729 return MMDRV_Message(wmld
, WIDM_PREPARE
, (DWORD
)lpWaveInHdr
, uSize
, TRUE
);
2732 /**************************************************************************
2733 * waveInUnprepareHeader [WINMM.@]
2735 UINT WINAPI
waveInUnprepareHeader(HWAVEIN hWaveIn
, WAVEHDR
* lpWaveInHdr
,
2740 TRACE("(%p, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
2742 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
2743 if (!(lpWaveInHdr
->dwFlags
& WHDR_PREPARED
)) {
2744 return MMSYSERR_NOERROR
;
2747 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
2748 return MMSYSERR_INVALHANDLE
;
2750 return MMDRV_Message(wmld
, WIDM_UNPREPARE
, (DWORD
)lpWaveInHdr
, uSize
, TRUE
);
2753 /**************************************************************************
2754 * waveInAddBuffer [WINMM.@]
2756 UINT WINAPI
waveInAddBuffer(HWAVEIN hWaveIn
,
2757 WAVEHDR
* lpWaveInHdr
, UINT uSize
)
2761 TRACE("(%p, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
2763 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
2764 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
2765 return MMSYSERR_INVALHANDLE
;
2767 return MMDRV_Message(wmld
, WIDM_ADDBUFFER
, (DWORD
)lpWaveInHdr
, uSize
, TRUE
);
2770 /**************************************************************************
2771 * waveInReset [WINMM.@]
2773 UINT WINAPI
waveInReset(HWAVEIN hWaveIn
)
2777 TRACE("(%p);\n", hWaveIn
);
2779 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
2780 return MMSYSERR_INVALHANDLE
;
2782 return MMDRV_Message(wmld
, WIDM_RESET
, 0L, 0L, TRUE
);
2785 /**************************************************************************
2786 * waveInStart [WINMM.@]
2788 UINT WINAPI
waveInStart(HWAVEIN hWaveIn
)
2792 TRACE("(%p);\n", hWaveIn
);
2794 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
2795 return MMSYSERR_INVALHANDLE
;
2797 return MMDRV_Message(wmld
, WIDM_START
, 0L, 0L, TRUE
);
2800 /**************************************************************************
2801 * waveInStop [WINMM.@]
2803 UINT WINAPI
waveInStop(HWAVEIN hWaveIn
)
2807 TRACE("(%p);\n", hWaveIn
);
2809 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
2810 return MMSYSERR_INVALHANDLE
;
2812 return MMDRV_Message(wmld
,WIDM_STOP
, 0L, 0L, TRUE
);
2815 /**************************************************************************
2816 * waveInGetPosition [WINMM.@]
2818 UINT WINAPI
waveInGetPosition(HWAVEIN hWaveIn
, LPMMTIME lpTime
,
2823 TRACE("(%p, %p, %u);\n", hWaveIn
, lpTime
, uSize
);
2825 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
2826 return MMSYSERR_INVALHANDLE
;
2828 return MMDRV_Message(wmld
, WIDM_GETPOS
, (DWORD
)lpTime
, uSize
, TRUE
);
2831 /**************************************************************************
2832 * waveInGetID [WINMM.@]
2834 UINT WINAPI
waveInGetID(HWAVEIN hWaveIn
, UINT
* lpuDeviceID
)
2838 TRACE("(%p, %p);\n", hWaveIn
, lpuDeviceID
);
2840 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
2842 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
2843 return MMSYSERR_INVALHANDLE
;
2845 *lpuDeviceID
= wmld
->uDeviceID
;
2846 return MMSYSERR_NOERROR
;
2849 /**************************************************************************
2850 * waveInMessage [WINMM.@]
2852 UINT WINAPI
waveInMessage(HWAVEIN hWaveIn
, UINT uMessage
,
2853 DWORD dwParam1
, DWORD dwParam2
)
2857 TRACE("(%p, %u, %ld, %ld)\n", hWaveIn
, uMessage
, dwParam1
, dwParam2
);
2859 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
) {
2860 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, TRUE
)) != NULL
) {
2861 return MMDRV_PhysicalFeatures(wmld
, uMessage
, dwParam1
, dwParam2
);
2863 return MMSYSERR_INVALHANDLE
;
2867 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
2868 return MMSYSERR_INVALPARAM
;
2871 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);