1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
6 * Copyright 1993 Martin Ayotte
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * 98/9 added Win32 MCI support
26 * 99/4 added mmTask and mmThread functions support
27 * added midiStream support
28 * 99/9 added support for loadable low level drivers
31 /* FIXME: I think there are some segmented vs. linear pointer weirdnesses
32 * and long term pointers to 16 bit space in here
41 #include "wine/mmsystem16.h"
42 #include "wine/winuser16.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(mmsys
);
51 static LPWINE_MM_IDATA lpFirstIData
= NULL
;
53 static LPWINE_MM_IDATA
MULTIMEDIA_GetIDataNoCheck(void)
55 DWORD pid
= GetCurrentProcessId();
56 LPWINE_MM_IDATA iData
;
58 for (iData
= lpFirstIData
; iData
; iData
= iData
->lpNextIData
) {
59 if (iData
->dwThisProcess
== pid
)
65 /**************************************************************************
66 * MULTIMEDIA_GetIData [internal]
68 LPWINE_MM_IDATA
MULTIMEDIA_GetIData(void)
70 LPWINE_MM_IDATA iData
= MULTIMEDIA_GetIDataNoCheck();
73 ERR("IData not found for pid=%08lx. Suicide !!!\n", GetCurrentProcessId());
80 /**************************************************************************
81 * MULTIMEDIA_CreateIData [internal]
83 static BOOL
MULTIMEDIA_CreateIData(HINSTANCE hInstDLL
)
85 LPWINE_MM_IDATA iData
;
87 iData
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WINE_MM_IDATA
));
91 iData
->hWinMM32Instance
= hInstDLL
;
92 iData
->dwThisProcess
= GetCurrentProcessId();
93 iData
->lpNextIData
= lpFirstIData
;
95 InitializeCriticalSection(&iData
->cs
);
96 iData
->cs
.DebugInfo
= (void*)__FILE__
": WinMM";
97 iData
->psStopEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
98 iData
->psLastEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
99 TRACE("Created IData (%p) for pid %08lx\n", iData
, iData
->dwThisProcess
);
103 /**************************************************************************
104 * MULTIMEDIA_DeleteIData [internal]
106 static void MULTIMEDIA_DeleteIData(void)
108 LPWINE_MM_IDATA iData
= MULTIMEDIA_GetIDataNoCheck();
109 LPWINE_MM_IDATA
* ppid
;
114 for (ppid
= &lpFirstIData
; *ppid
; ppid
= &(*ppid
)->lpNextIData
) {
115 if (*ppid
== iData
) {
116 *ppid
= iData
->lpNextIData
;
120 /* FIXME: should also free content and resources allocated
122 CloseHandle(iData
->psStopEvent
);
123 CloseHandle(iData
->psLastEvent
);
124 DeleteCriticalSection(&iData
->cs
);
125 HeapFree(GetProcessHeap(), 0, iData
);
129 /**************************************************************************
130 * DllEntryPoint (WINMM.init)
132 * WINMM DLL entry point
135 BOOL WINAPI
WINMM_LibMain(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID fImpLoad
)
137 TRACE("0x%x 0x%lx %p\n", hInstDLL
, fdwReason
, fImpLoad
);
140 case DLL_PROCESS_ATTACH
:
141 if (!MULTIMEDIA_CreateIData(hInstDLL
))
143 if (!MULTIMEDIA_MciInit() || !MMDRV_Init()) {
144 MULTIMEDIA_DeleteIData();
148 case DLL_PROCESS_DETACH
:
149 MULTIMEDIA_DeleteIData();
151 case DLL_THREAD_ATTACH
:
152 case DLL_THREAD_DETACH
:
158 /**************************************************************************
159 * DllEntryPoint (MMSYSTEM.2046)
161 * MMSYSTEM DLL entry point
164 BOOL WINAPI
MMSYSTEM_LibMain(DWORD fdwReason
, HINSTANCE hinstDLL
, WORD ds
,
165 WORD wHeapSize
, DWORD dwReserved1
, WORD wReserved2
)
168 LPWINE_MM_IDATA iData
;
170 TRACE("0x%x 0x%lx\n", hinstDLL
, fdwReason
);
173 case DLL_PROCESS_ATTACH
:
174 /* need to load WinMM in order to:
175 * - initiate correctly shared variables (MULTIMEDIA_Init())
176 * - create correctly the per process WINE_MM_IDATA chunk
178 hndl
= LoadLibraryA("WINMM.DLL");
181 ERR("Could not load sibling WinMM.dll\n");
184 iData
= MULTIMEDIA_GetIData();
185 iData
->hWinMM16Instance
= hinstDLL
;
186 iData
->h16Module32
= hndl
;
188 case DLL_PROCESS_DETACH
:
189 iData
= MULTIMEDIA_GetIData();
190 FreeLibrary(iData
->h16Module32
);
192 case DLL_THREAD_ATTACH
:
193 case DLL_THREAD_DETACH
:
199 /**************************************************************************
200 * MMSYSTEM_WEP [MMSYSTEM.1]
202 int WINAPI
MMSYSTEM_WEP(HINSTANCE16 hInstance
, WORD wDataSeg
,
203 WORD cbHeapSize
, LPSTR lpCmdLine
)
205 FIXME("STUB: Unloading MMSystem DLL ... hInst=%04X \n", hInstance
);
209 void MMSYSTEM_MMTIME32to16(LPMMTIME16 mmt16
, const MMTIME
* mmt32
)
211 mmt16
->wType
= mmt32
->wType
;
212 /* layout of rest is the same for 32/16,
213 * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
215 memcpy(&(mmt16
->u
), &(mmt32
->u
), sizeof(mmt16
->u
));
218 void MMSYSTEM_MMTIME16to32(LPMMTIME mmt32
, const MMTIME16
* mmt16
)
220 mmt32
->wType
= mmt16
->wType
;
221 /* layout of rest is the same for 32/16,
222 * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
224 memcpy(&(mmt32
->u
), &(mmt16
->u
), sizeof(mmt16
->u
));
227 static HMMIO
get_mmioFromFile(LPCWSTR lpszName
)
233 ret
= mmioOpenW((LPWSTR
)lpszName
, NULL
,
234 MMIO_ALLOCBUF
| MMIO_READ
| MMIO_DENYWRITE
);
235 if (ret
!= 0) return ret
;
236 if (SearchPathW(NULL
, lpszName
, NULL
, sizeof(buf
)/sizeof(buf
[0]), buf
, &dummy
))
238 return mmioOpenW(buf
, NULL
,
239 MMIO_ALLOCBUF
| MMIO_READ
| MMIO_DENYWRITE
);
244 static HMMIO
get_mmioFromProfile(UINT uFlags
, LPCWSTR lpszName
)
249 HKEY hRegSnd
, hRegApp
, hScheme
, hSnd
;
250 DWORD err
, type
, count
;
252 static WCHAR wszSounds
[] = {'S','o','u','n','d','s',0};
253 static WCHAR wszDefault
[] = {'D','e','f','a','u','l','t',0};
254 static WCHAR wszKey
[] = {'A','p','p','E','v','e','n','t','s','\\',
255 'S','c','h','e','m','e','s','\\',
257 static WCHAR wszDotDefault
[] = {'.','D','e','f','a','u','l','t',0};
258 static WCHAR wszNull
[] = {0};
260 TRACE("searching in SystemSound list for %s\n", debugstr_w(lpszName
));
261 GetProfileStringW(wszSounds
, (LPWSTR
)lpszName
, wszNull
, str
, sizeof(str
)/sizeof(str
[0]));
262 if (lstrlenW(str
) == 0)
264 if (uFlags
& SND_NODEFAULT
) goto next
;
265 GetProfileStringW(wszSounds
, wszDefault
, wszNull
, str
, sizeof(str
)/sizeof(str
[0]));
266 if (lstrlenW(str
) == 0) goto next
;
268 for (ptr
= str
; *ptr
&& *ptr
!= ','; ptr
++);
270 hmmio
= mmioOpenW(str
, NULL
, MMIO_ALLOCBUF
| MMIO_READ
| MMIO_DENYWRITE
);
271 if (hmmio
!= 0) return hmmio
;
273 /* we look up the registry under
274 * HKCU\AppEvents\Schemes\Apps\.Default
275 * HKCU\AppEvents\Schemes\Apps\<AppName>
277 if (RegOpenKeyW(HKEY_CURRENT_USER
, wszKey
, &hRegSnd
) != 0) goto none
;
278 if (uFlags
& SND_APPLICATION
)
281 if (GetModuleFileNameW(0, str
, sizeof(str
)/sizeof(str
[0])))
283 for (ptr
= str
+ lstrlenW(str
) - 1; ptr
>= str
; ptr
--)
285 if (*ptr
== '.') *ptr
= 0;
288 err
= RegOpenKeyW(hRegSnd
, str
, &hRegApp
);
296 err
= RegOpenKeyW(hRegSnd
, wszDotDefault
, &hRegApp
);
298 RegCloseKey(hRegSnd
);
299 if (err
!= 0) goto none
;
300 err
= RegOpenKeyW(hRegApp
, lpszName
, &hScheme
);
301 RegCloseKey(hRegApp
);
302 if (err
!= 0) goto none
;
303 err
= RegOpenKeyW(hScheme
, wszDotDefault
, &hSnd
);
304 RegCloseKey(hScheme
);
305 if (err
!= 0) goto none
;
306 count
= sizeof(str
)/sizeof(str
[0]);
307 err
= RegQueryValueExW(hSnd
, NULL
, 0, &type
, (LPBYTE
)str
, &count
);
309 if (err
!= 0 || !*str
) goto none
;
310 hmmio
= mmioOpenW(str
, NULL
, MMIO_ALLOCBUF
| MMIO_READ
| MMIO_DENYWRITE
);
311 if (hmmio
) return hmmio
;
313 WARN("can't find SystemSound='%s' !\n", debugstr_w(lpszName
));
317 struct playsound_data
323 static void CALLBACK
PlaySound_Callback(HWAVEOUT hwo
, UINT uMsg
,
325 DWORD dwParam1
, DWORD dwParam2
)
327 struct playsound_data
* s
= (struct playsound_data
*)dwInstance
;
334 InterlockedIncrement(&s
->dwEventCount
);
335 TRACE("Returning waveHdr=%lx\n", dwParam1
);
339 ERR("Unknown uMsg=%d\n", uMsg
);
343 static void PlaySound_WaitDone(struct playsound_data
* s
)
346 ResetEvent(s
->hEvent
);
347 if (InterlockedDecrement(&s
->dwEventCount
) >= 0) break;
348 InterlockedIncrement(&s
->dwEventCount
);
350 WaitForSingleObject(s
->hEvent
, INFINITE
);
354 static BOOL
PlaySound_IsString(DWORD fdwSound
, const void* psz
)
356 /* SND_RESOURCE is 0x40004 while
357 * SND_MEMORY is 0x00004
359 switch (fdwSound
& (SND_RESOURCE
|SND_ALIAS
|SND_FILENAME
))
361 case SND_RESOURCE
: return HIWORD(psz
) != 0; /* by name or by ID ? */
362 case SND_MEMORY
: return FALSE
;
363 case SND_ALIAS
: /* what about ALIAS_ID ??? */
366 default: FIXME("WTF\n"); return FALSE
;
370 static void PlaySound_Free(WINE_PLAYSOUND
* wps
)
372 LPWINE_MM_IDATA iData
= MULTIMEDIA_GetIData();
375 EnterCriticalSection(&iData
->cs
);
376 for (p
= &iData
->lpPlaySound
; *p
&& *p
!= wps
; p
= &((*p
)->lpNext
));
377 if (*p
) *p
= (*p
)->lpNext
;
378 if (iData
->lpPlaySound
== NULL
) SetEvent(iData
->psLastEvent
);
379 LeaveCriticalSection(&iData
->cs
);
380 if (wps
->bAlloc
) HeapFree(GetProcessHeap(), 0, (void*)wps
->pszSound
);
381 HeapFree(GetProcessHeap(), 0, wps
);
384 static WINE_PLAYSOUND
* PlaySound_Alloc(const void* pszSound
, HMODULE hmod
,
385 DWORD fdwSound
, BOOL bUnicode
)
389 wps
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wps
));
390 if (!wps
) return NULL
;
393 wps
->fdwSound
= fdwSound
;
394 if (PlaySound_IsString(fdwSound
, pszSound
))
398 if (fdwSound
& SND_ASYNC
)
400 wps
->pszSound
= HeapAlloc(GetProcessHeap(), 0,
401 (lstrlenW(pszSound
)+1) * sizeof(WCHAR
));
402 if (!wps
->pszSound
) goto oom_error
;
403 lstrcpyW((LPWSTR
)wps
->pszSound
, pszSound
);
407 wps
->pszSound
= pszSound
;
411 wps
->pszSound
= HEAP_strdupAtoW(GetProcessHeap(), 0, pszSound
);
412 if (!wps
->pszSound
) goto oom_error
;
417 wps
->pszSound
= pszSound
;
425 static DWORD WINAPI
proc_PlaySound(LPVOID arg
)
427 WINE_PLAYSOUND
* wps
= (WINE_PLAYSOUND
*)arg
;
428 LPWINE_MM_IDATA iData
= MULTIMEDIA_GetIData();
433 LPWAVEFORMATEX lpWaveFormat
= NULL
;
435 LPWAVEHDR waveHdr
= NULL
;
436 INT count
, bufsize
, left
, index
;
437 struct playsound_data s
;
442 TRACE("SoundName='%s' !\n", debugstr_w(wps
->pszSound
));
444 /* if resource, grab it */
445 if ((wps
->fdwSound
& SND_RESOURCE
) == SND_RESOURCE
) {
446 static WCHAR wszWave
[] = {'W','A','V','E',0};
450 if ((hRes
= FindResourceW(wps
->hMod
, wps
->pszSound
, wszWave
)) == 0 ||
451 (hGlob
= LoadResource(wps
->hMod
, hRes
)) == 0)
453 if ((data
= LockResource(hGlob
)) == NULL
) {
459 data
= (void*)wps
->pszSound
;
461 /* construct an MMIO stream (either in memory, or from a file */
462 if (wps
->fdwSound
& SND_MEMORY
)
463 { /* NOTE: SND_RESOURCE has the SND_MEMORY bit set */
466 memset(&mminfo
, 0, sizeof(mminfo
));
467 mminfo
.fccIOProc
= FOURCC_MEM
;
468 mminfo
.pchBuffer
= (LPSTR
)data
;
469 mminfo
.cchBuffer
= -1; /* FIXME: when a resource, could grab real size */
470 TRACE("Memory sound %p\n", data
);
471 hmmio
= mmioOpenW(NULL
, &mminfo
, MMIO_READ
);
473 else if (wps
->fdwSound
& SND_ALIAS
)
475 hmmio
= get_mmioFromProfile(wps
->fdwSound
, wps
->pszSound
);
477 else if (wps
->fdwSound
& SND_FILENAME
)
479 hmmio
= get_mmioFromFile(wps
->pszSound
);
483 if ((hmmio
= get_mmioFromProfile(wps
->fdwSound
| SND_NODEFAULT
, wps
->pszSound
)) == 0)
485 if ((hmmio
= get_mmioFromFile(wps
->pszSound
)) == 0)
487 hmmio
= get_mmioFromProfile(wps
->fdwSound
, wps
->pszSound
);
491 if (hmmio
== 0) goto errCleanUp
;
493 if (mmioDescend(hmmio
, &ckMainRIFF
, NULL
, 0))
496 TRACE("ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
497 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
, ckMainRIFF
.cksize
);
499 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
500 (ckMainRIFF
.fccType
!= mmioFOURCC('W', 'A', 'V', 'E')))
503 mmckInfo
.ckid
= mmioFOURCC('f', 'm', 't', ' ');
504 if (mmioDescend(hmmio
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
))
507 TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
508 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
, mmckInfo
.cksize
);
510 lpWaveFormat
= HeapAlloc(GetProcessHeap(), 0, mmckInfo
.cksize
);
511 if (mmioRead(hmmio
, (HPSTR
)lpWaveFormat
, mmckInfo
.cksize
) < sizeof(WAVEFORMAT
))
514 TRACE("wFormatTag=%04X !\n", lpWaveFormat
->wFormatTag
);
515 TRACE("nChannels=%d \n", lpWaveFormat
->nChannels
);
516 TRACE("nSamplesPerSec=%ld\n", lpWaveFormat
->nSamplesPerSec
);
517 TRACE("nAvgBytesPerSec=%ld\n", lpWaveFormat
->nAvgBytesPerSec
);
518 TRACE("nBlockAlign=%d \n", lpWaveFormat
->nBlockAlign
);
519 TRACE("wBitsPerSample=%u !\n", lpWaveFormat
->wBitsPerSample
);
521 /* move to end of 'fmt ' chunk */
522 mmioAscend(hmmio
, &mmckInfo
, 0);
524 mmckInfo
.ckid
= mmioFOURCC('d', 'a', 't', 'a');
525 if (mmioDescend(hmmio
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
))
528 TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX\n",
529 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
, mmckInfo
.cksize
);
531 s
.hEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
533 if (waveOutOpen(&hWave
, WAVE_MAPPER
, lpWaveFormat
, (DWORD
)PlaySound_Callback
,
534 (DWORD
)&s
, CALLBACK_FUNCTION
) != MMSYSERR_NOERROR
)
537 /* make it so that 3 buffers per second are needed */
538 bufsize
= (((lpWaveFormat
->nAvgBytesPerSec
/ 3) - 1) / lpWaveFormat
->nBlockAlign
+ 1) *
539 lpWaveFormat
->nBlockAlign
;
540 waveHdr
= HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WAVEHDR
) + 2 * bufsize
);
541 waveHdr
[0].lpData
= (char*)waveHdr
+ 2 * sizeof(WAVEHDR
);
542 waveHdr
[1].lpData
= (char*)waveHdr
+ 2 * sizeof(WAVEHDR
) + bufsize
;
543 waveHdr
[0].dwUser
= waveHdr
[1].dwUser
= 0L;
544 waveHdr
[0].dwLoops
= waveHdr
[1].dwLoops
= 0L;
545 waveHdr
[0].dwFlags
= waveHdr
[1].dwFlags
= 0L;
546 waveHdr
[0].dwBufferLength
= waveHdr
[1].dwBufferLength
= bufsize
;
547 if (waveOutPrepareHeader(hWave
, &waveHdr
[0], sizeof(WAVEHDR
)) ||
548 waveOutPrepareHeader(hWave
, &waveHdr
[1], sizeof(WAVEHDR
))) {
554 left
= mmckInfo
.cksize
;
555 s
.dwEventCount
= 1L; /* for first buffer */
557 mmioSeek(hmmio
, mmckInfo
.dwDataOffset
, SEEK_SET
);
560 if (WaitForSingleObject(iData
->psStopEvent
, 0) == WAIT_OBJECT_0
)
565 count
= mmioRead(hmmio
, waveHdr
[index
].lpData
, min(bufsize
, left
));
566 if (count
< 1) break;
568 waveHdr
[index
].dwBufferLength
= count
;
569 waveHdr
[index
].dwFlags
&= ~WHDR_DONE
;
570 if (waveOutWrite(hWave
, &waveHdr
[index
], sizeof(WAVEHDR
)) == MMSYSERR_NOERROR
) {
572 PlaySound_WaitDone(&s
);
574 else FIXME("Couldn't play header\n");
577 } while (wps
->bLoop
);
579 PlaySound_WaitDone(&s
); /* for last buffer */
582 waveOutUnprepareHeader(hWave
, &waveHdr
[0], sizeof(WAVEHDR
));
583 waveOutUnprepareHeader(hWave
, &waveHdr
[1], sizeof(WAVEHDR
));
586 TRACE("Done playing='%s' => %s!\n", debugstr_w(wps
->pszSound
), bRet
? "ok" : "ko");
587 CloseHandle(s
.hEvent
);
588 if (waveHdr
) HeapFree(GetProcessHeap(), 0, waveHdr
);
589 if (lpWaveFormat
) HeapFree(GetProcessHeap(), 0, lpWaveFormat
);
590 if (hWave
) while (waveOutClose(hWave
) == WAVERR_STILLPLAYING
) Sleep(100);
591 if (hmmio
) mmioClose(hmmio
, 0);
598 static BOOL
MULTIMEDIA_PlaySound(const void* pszSound
, HMODULE hmod
, DWORD fdwSound
, BOOL bUnicode
)
600 WINE_PLAYSOUND
* wps
= NULL
;
601 LPWINE_MM_IDATA iData
= MULTIMEDIA_GetIData();
603 TRACE("pszSound='%p' hmod=%04X fdwSound=%08lX\n",
604 pszSound
, hmod
, fdwSound
);
606 /* FIXME? I see no difference between SND_NOWAIT and SND_NOSTOP !
607 * there could be one if several sounds can be played at once...
609 if ((fdwSound
& (SND_NOWAIT
| SND_NOSTOP
)) && iData
->lpPlaySound
!= NULL
)
612 /* alloc internal structure, if we need to play something */
613 if (pszSound
&& !(fdwSound
& SND_PURGE
))
615 if (!(wps
= PlaySound_Alloc(pszSound
, hmod
, fdwSound
, bUnicode
)))
619 EnterCriticalSection(&iData
->cs
);
620 /* since several threads can enter PlaySound in parallel, we're not
621 * sure, at this point, that another thread didn't start a new playsound
623 while (iData
->lpPlaySound
!= NULL
)
625 ResetEvent(iData
->psLastEvent
);
626 /* FIXME: doc says we have to stop all instances of pszSound if it's non
627 * NULL... as of today, we stop all playing instances */
628 SetEvent(iData
->psStopEvent
);
630 LeaveCriticalSection(&iData
->cs
);
631 WaitForSingleObject(iData
->psLastEvent
, INFINITE
);
632 EnterCriticalSection(&iData
->cs
);
634 ResetEvent(iData
->psStopEvent
);
637 wps
->lpNext
= iData
->lpPlaySound
;
638 iData
->lpPlaySound
= wps
;
639 LeaveCriticalSection(&iData
->cs
);
641 if (!pszSound
|| (fdwSound
& SND_PURGE
)) return TRUE
;
643 if (fdwSound
& SND_ASYNC
)
646 wps
->bLoop
= (fdwSound
& SND_LOOP
) ? TRUE
: FALSE
;
647 if (CreateThread(NULL
, 0, proc_PlaySound
, wps
, 0, &id
) != 0)
650 else return proc_PlaySound(wps
);
657 /**************************************************************************
658 * PlaySoundA [WINMM.@]
660 BOOL WINAPI
PlaySoundA(LPCSTR pszSoundA
, HMODULE hmod
, DWORD fdwSound
)
662 return MULTIMEDIA_PlaySound(pszSoundA
, hmod
, fdwSound
, FALSE
);
665 /**************************************************************************
666 * PlaySoundW [WINMM.@]
668 BOOL WINAPI
PlaySoundW(LPCWSTR pszSoundW
, HMODULE hmod
, DWORD fdwSound
)
670 return MULTIMEDIA_PlaySound(pszSoundW
, hmod
, fdwSound
, TRUE
);
673 /**************************************************************************
674 * PlaySound [MMSYSTEM.3]
676 BOOL16 WINAPI
PlaySound16(LPCSTR pszSound
, HMODULE16 hmod
, DWORD fdwSound
)
681 ReleaseThunkLock(&lc
);
682 retv
= PlaySoundA(pszSound
, hmod
, fdwSound
);
683 RestoreThunkLock(lc
);
688 /**************************************************************************
689 * sndPlaySoundA [WINMM.@]
691 BOOL WINAPI
sndPlaySoundA(LPCSTR pszSoundA
, UINT uFlags
)
693 uFlags
&= ~(SND_ASYNC
|SND_LOOP
|SND_MEMORY
|SND_NODEFAULT
|SND_NOSTOP
|SND_SYNC
);
694 return MULTIMEDIA_PlaySound(pszSoundA
, 0, uFlags
, FALSE
);
697 /**************************************************************************
698 * sndPlaySoundW [WINMM.@]
700 BOOL WINAPI
sndPlaySoundW(LPCWSTR pszSound
, UINT uFlags
)
702 uFlags
&= ~(SND_ASYNC
|SND_LOOP
|SND_MEMORY
|SND_NODEFAULT
|SND_NOSTOP
|SND_SYNC
);
703 return MULTIMEDIA_PlaySound(pszSound
, 0, uFlags
, TRUE
);
706 /**************************************************************************
707 * sndPlaySound [MMSYSTEM.2]
709 BOOL16 WINAPI
sndPlaySound16(LPCSTR lpszSoundName
, UINT16 uFlags
)
714 ReleaseThunkLock(&lc
);
715 retv
= sndPlaySoundA(lpszSoundName
, uFlags
);
716 RestoreThunkLock(lc
);
721 /**************************************************************************
722 * mmsystemGetVersion [MMSYSTEM.5]
723 * return value borrowed from Win95 winmm.dll ;)
725 UINT16 WINAPI
mmsystemGetVersion16(void)
727 return mmsystemGetVersion();
730 /**************************************************************************
731 * mmsystemGetVersion [WINMM.@]
733 UINT WINAPI
mmsystemGetVersion(void)
735 TRACE("3.10 (Win95?)\n");
739 /**************************************************************************
740 * DriverCallback [WINMM.@]
742 BOOL WINAPI
DriverCallback(DWORD dwCallBack
, UINT uFlags
, HDRVR hDev
,
743 UINT wMsg
, DWORD dwUser
, DWORD dwParam1
,
746 TRACE("(%08lX, %04X, %04X, %04X, %08lX, %08lX, %08lX); !\n",
747 dwCallBack
, uFlags
, hDev
, wMsg
, dwUser
, dwParam1
, dwParam2
);
749 switch (uFlags
& DCB_TYPEMASK
) {
753 WARN("uFlags=%04X has null DCB value, but dwCallBack=%08lX is not null !\n", uFlags
, dwCallBack
);
756 TRACE("Window(%04lX) handle=%04X!\n", dwCallBack
, hDev
);
757 PostMessageA((HWND
)dwCallBack
, wMsg
, hDev
, dwParam1
);
759 case DCB_TASK
: /* aka DCB_THREAD */
760 TRACE("Task(%04lx) !\n", dwCallBack
);
761 PostThreadMessageA(dwCallBack
, wMsg
, hDev
, dwParam1
);
764 TRACE("Function (32 bit) !\n");
765 ((LPDRVCALLBACK
)dwCallBack
)(hDev
, wMsg
, dwUser
, dwParam1
, dwParam2
);
768 TRACE("Event(%08lx) !\n", dwCallBack
);
769 SetEvent((HANDLE
)dwCallBack
);
771 case 6: /* I would dub it DCB_MMTHREADSIGNAL */
772 /* this is an undocumented DCB_ value used for mmThreads
773 * loword of dwCallBack contains the handle of the lpMMThd block
774 * which dwSignalCount has to be incremented
777 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(LOWORD(dwCallBack
), 0) );
779 TRACE("mmThread (%04x, %p) !\n", LOWORD(dwCallBack
), lpMMThd
);
780 /* same as mmThreadSignal16 */
781 InterlockedIncrement(&lpMMThd
->dwSignalCount
);
782 SetEvent(lpMMThd
->hEvent
);
783 /* some other stuff on lpMMThd->hVxD */
788 /* this is an undocumented DCB_ value for... I don't know */
792 WARN("Unknown callback type %d\n", uFlags
& DCB_TYPEMASK
);
799 /**************************************************************************
800 * DriverCallback [MMSYSTEM.31]
802 BOOL16 WINAPI
DriverCallback16(DWORD dwCallBack
, UINT16 uFlags
, HDRVR16 hDev
,
803 WORD wMsg
, DWORD dwUser
, DWORD dwParam1
,
806 return DriverCallback(dwCallBack
, uFlags
, hDev
, wMsg
, dwUser
, dwParam1
, dwParam2
);
809 /**************************************************************************
810 * Mixer devices. New to Win95
813 /**************************************************************************
814 * find out the real mixer ID depending on hmix (depends on dwFlags)
816 static LPWINE_MIXER
MIXER_GetDev(HMIXEROBJ hmix
, DWORD dwFlags
)
818 LPWINE_MIXER lpwm
= NULL
;
820 switch (dwFlags
& 0xF0000000ul
) {
821 case MIXER_OBJECTF_MIXER
:
822 lpwm
= (LPWINE_MIXER
)MMDRV_Get(hmix
, MMDRV_MIXER
, TRUE
);
824 case MIXER_OBJECTF_HMIXER
:
825 lpwm
= (LPWINE_MIXER
)MMDRV_Get(hmix
, MMDRV_MIXER
, FALSE
);
827 case MIXER_OBJECTF_WAVEOUT
:
828 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEOUT
, TRUE
, MMDRV_MIXER
);
830 case MIXER_OBJECTF_HWAVEOUT
:
831 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEOUT
, FALSE
, MMDRV_MIXER
);
833 case MIXER_OBJECTF_WAVEIN
:
834 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEIN
, TRUE
, MMDRV_MIXER
);
836 case MIXER_OBJECTF_HWAVEIN
:
837 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEIN
, FALSE
, MMDRV_MIXER
);
839 case MIXER_OBJECTF_MIDIOUT
:
840 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIOUT
, TRUE
, MMDRV_MIXER
);
842 case MIXER_OBJECTF_HMIDIOUT
:
843 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIOUT
, FALSE
, MMDRV_MIXER
);
845 case MIXER_OBJECTF_MIDIIN
:
846 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIIN
, TRUE
, MMDRV_MIXER
);
848 case MIXER_OBJECTF_HMIDIIN
:
849 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIIN
, FALSE
, MMDRV_MIXER
);
851 case MIXER_OBJECTF_AUX
:
852 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_AUX
, TRUE
, MMDRV_MIXER
);
855 FIXME("Unsupported flag (%08lx)\n", dwFlags
& 0xF0000000ul
);
861 /**************************************************************************
862 * mixerGetNumDevs [WINMM.@]
864 UINT WINAPI
mixerGetNumDevs(void)
866 return MMDRV_GetNum(MMDRV_MIXER
);
869 /**************************************************************************
870 * mixerGetNumDevs [MMSYSTEM.800]
872 UINT16 WINAPI
mixerGetNumDevs16(void)
874 return MMDRV_GetNum(MMDRV_MIXER
);
877 /**************************************************************************
878 * mixerGetDevCapsA [WINMM.@]
880 UINT WINAPI
mixerGetDevCapsA(UINT devid
, LPMIXERCAPSA mixcaps
, UINT size
)
884 if ((wmld
= MMDRV_Get(devid
, MMDRV_MIXER
, TRUE
)) == NULL
)
885 return MMSYSERR_BADDEVICEID
;
887 return MMDRV_Message(wmld
, MXDM_GETDEVCAPS
, (DWORD
)mixcaps
, size
, TRUE
);
890 /**************************************************************************
891 * mixerGetDevCapsW [WINMM.@]
893 UINT WINAPI
mixerGetDevCapsW(UINT devid
, LPMIXERCAPSW mixcaps
, UINT size
)
896 UINT ret
= mixerGetDevCapsA(devid
, &micA
, sizeof(micA
));
898 if (ret
== MMSYSERR_NOERROR
) {
899 mixcaps
->wMid
= micA
.wMid
;
900 mixcaps
->wPid
= micA
.wPid
;
901 mixcaps
->vDriverVersion
= micA
.vDriverVersion
;
902 MultiByteToWideChar( CP_ACP
, 0, micA
.szPname
, -1, mixcaps
->szPname
,
903 sizeof(mixcaps
->szPname
)/sizeof(WCHAR
) );
904 mixcaps
->fdwSupport
= micA
.fdwSupport
;
905 mixcaps
->cDestinations
= micA
.cDestinations
;
910 /**************************************************************************
911 * mixerGetDevCaps [MMSYSTEM.801]
913 UINT16 WINAPI
mixerGetDevCaps16(UINT16 devid
, LPMIXERCAPS16 mixcaps
,
917 UINT ret
= mixerGetDevCapsA(devid
, &micA
, sizeof(micA
));
919 if (ret
== MMSYSERR_NOERROR
) {
920 mixcaps
->wMid
= micA
.wMid
;
921 mixcaps
->wPid
= micA
.wPid
;
922 mixcaps
->vDriverVersion
= micA
.vDriverVersion
;
923 strcpy(mixcaps
->szPname
, micA
.szPname
);
924 mixcaps
->fdwSupport
= micA
.fdwSupport
;
925 mixcaps
->cDestinations
= micA
.cDestinations
;
930 static UINT
MMSYSTEM_mixerOpen(LPHMIXER lphMix
, UINT uDeviceID
, DWORD dwCallback
,
931 DWORD dwInstance
, DWORD fdwOpen
, BOOL bFrom32
)
938 TRACE("(%p, %d, %08lx, %08lx, %08lx)\n",
939 lphMix
, uDeviceID
, dwCallback
, dwInstance
, fdwOpen
);
941 wmld
= MMDRV_Alloc(sizeof(WINE_MIXER
), MMDRV_MIXER
, &hMix
, &fdwOpen
,
942 &dwCallback
, &dwInstance
, bFrom32
);
944 wmld
->uDeviceID
= uDeviceID
;
946 mod
.dwCallback
= dwCallback
;
947 mod
.dwInstance
= dwInstance
;
949 dwRet
= MMDRV_Open(wmld
, MXDM_OPEN
, (DWORD
)&mod
, fdwOpen
);
951 if (dwRet
!= MMSYSERR_NOERROR
) {
952 MMDRV_Free(hMix
, wmld
);
955 if (lphMix
) *lphMix
= hMix
;
956 TRACE("=> %ld hMixer=%04x\n", dwRet
, hMix
);
961 /**************************************************************************
962 * mixerOpen [WINMM.@]
964 UINT WINAPI
mixerOpen(LPHMIXER lphMix
, UINT uDeviceID
, DWORD dwCallback
,
965 DWORD dwInstance
, DWORD fdwOpen
)
967 return MMSYSTEM_mixerOpen(lphMix
, uDeviceID
,
968 dwCallback
, dwInstance
, fdwOpen
, TRUE
);
971 /**************************************************************************
972 * mixerOpen [MMSYSTEM.802]
974 UINT16 WINAPI
mixerOpen16(LPHMIXER16 lphmix
, UINT16 uDeviceID
, DWORD dwCallback
,
975 DWORD dwInstance
, DWORD fdwOpen
)
980 ret
= MMSYSTEM_mixerOpen(&hmix
, uDeviceID
,
981 dwCallback
, dwInstance
, fdwOpen
, FALSE
);
982 if (lphmix
) *lphmix
= hmix
;
986 /**************************************************************************
987 * mixerClose [WINMM.@]
989 UINT WINAPI
mixerClose(HMIXER hMix
)
994 TRACE("(%04x)\n", hMix
);
996 if ((wmld
= MMDRV_Get(hMix
, MMDRV_MIXER
, FALSE
)) == NULL
) return MMSYSERR_INVALHANDLE
;
998 dwRet
= MMDRV_Close(wmld
, MXDM_CLOSE
);
999 MMDRV_Free(hMix
, wmld
);
1004 /**************************************************************************
1005 * mixerClose [MMSYSTEM.803]
1007 UINT16 WINAPI
mixerClose16(HMIXER16 hMix
)
1009 return mixerClose(hMix
);
1012 /**************************************************************************
1013 * mixerGetID [WINMM.@]
1015 UINT WINAPI
mixerGetID(HMIXEROBJ hmix
, LPUINT lpid
, DWORD fdwID
)
1019 TRACE("(%04x %p %08lx)\n", hmix
, lpid
, fdwID
);
1021 if ((lpwm
= MIXER_GetDev(hmix
, fdwID
)) == NULL
) {
1022 return MMSYSERR_INVALHANDLE
;
1026 *lpid
= lpwm
->mld
.uDeviceID
;
1028 return MMSYSERR_NOERROR
;
1031 /**************************************************************************
1032 * mixerGetID (MMSYSTEM.806)
1034 UINT16 WINAPI
mixerGetID16(HMIXEROBJ16 hmix
, LPUINT16 lpid
, DWORD fdwID
)
1037 UINT ret
= mixerGetID(hmix
, &xid
, fdwID
);
1044 /**************************************************************************
1045 * mixerGetControlDetailsA [WINMM.@]
1047 UINT WINAPI
mixerGetControlDetailsA(HMIXEROBJ hmix
, LPMIXERCONTROLDETAILS lpmcdA
,
1052 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcdA
, fdwDetails
);
1054 if ((lpwm
= MIXER_GetDev(hmix
, fdwDetails
)) == NULL
)
1055 return MMSYSERR_INVALHANDLE
;
1057 if (lpmcdA
== NULL
|| lpmcdA
->cbStruct
!= sizeof(*lpmcdA
))
1058 return MMSYSERR_INVALPARAM
;
1060 return MMDRV_Message(&lpwm
->mld
, MXDM_GETCONTROLDETAILS
, (DWORD
)lpmcdA
,
1064 /**************************************************************************
1065 * mixerGetControlDetailsW [WINMM.@]
1067 UINT WINAPI
mixerGetControlDetailsW(HMIXEROBJ hmix
, LPMIXERCONTROLDETAILS lpmcd
, DWORD fdwDetails
)
1069 DWORD ret
= MMSYSERR_NOTENABLED
;
1071 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcd
, fdwDetails
);
1073 if (lpmcd
== NULL
|| lpmcd
->cbStruct
!= sizeof(*lpmcd
))
1074 return MMSYSERR_INVALPARAM
;
1076 switch (fdwDetails
& MIXER_GETCONTROLDETAILSF_QUERYMASK
) {
1077 case MIXER_GETCONTROLDETAILSF_VALUE
:
1078 /* can savely use W structure as it is, no string inside */
1079 ret
= mixerGetControlDetailsA(hmix
, lpmcd
, fdwDetails
);
1081 case MIXER_GETCONTROLDETAILSF_LISTTEXT
:
1083 MIXERCONTROLDETAILS_LISTTEXTW
*pDetailsW
= (MIXERCONTROLDETAILS_LISTTEXTW
*)lpmcd
->paDetails
;
1084 MIXERCONTROLDETAILS_LISTTEXTA
*pDetailsA
;
1085 int size
= max(1, lpmcd
->cChannels
) * sizeof(MIXERCONTROLDETAILS_LISTTEXTA
);
1088 if (lpmcd
->u
.cMultipleItems
!= 0) {
1089 size
*= lpmcd
->u
.cMultipleItems
;
1091 pDetailsA
= (MIXERCONTROLDETAILS_LISTTEXTA
*)HeapAlloc(GetProcessHeap(), 0, size
);
1092 lpmcd
->paDetails
= pDetailsA
;
1093 lpmcd
->cbDetails
= sizeof(MIXERCONTROLDETAILS_LISTTEXTA
);
1094 /* set up lpmcd->paDetails */
1095 ret
= mixerGetControlDetailsA(hmix
, lpmcd
, fdwDetails
);
1096 /* copy from lpmcd->paDetails back to paDetailsW; */
1097 if(ret
== MMSYSERR_NOERROR
) {
1098 for(i
=0;i
<lpmcd
->u
.cMultipleItems
*lpmcd
->cChannels
;i
++) {
1099 pDetailsW
->dwParam1
= pDetailsA
->dwParam1
;
1100 pDetailsW
->dwParam2
= pDetailsA
->dwParam2
;
1101 MultiByteToWideChar( CP_ACP
, 0, pDetailsA
->szName
, -1,
1103 sizeof(pDetailsW
->szName
)/sizeof(WCHAR
) );
1107 pDetailsA
-= lpmcd
->u
.cMultipleItems
*lpmcd
->cChannels
;
1108 pDetailsW
-= lpmcd
->u
.cMultipleItems
*lpmcd
->cChannels
;
1110 HeapFree(GetProcessHeap(), 0, pDetailsA
);
1111 lpmcd
->paDetails
= pDetailsW
;
1112 lpmcd
->cbDetails
= sizeof(MIXERCONTROLDETAILS_LISTTEXTW
);
1116 ERR("Unsupported fdwDetails=0x%08lx\n", fdwDetails
);
1122 /**************************************************************************
1123 * mixerGetControlDetails [MMSYSTEM.808]
1125 UINT16 WINAPI
mixerGetControlDetails16(HMIXEROBJ16 hmix
,
1126 LPMIXERCONTROLDETAILS16 lpmcd
,
1129 DWORD ret
= MMSYSERR_NOTENABLED
;
1132 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcd
, fdwDetails
);
1134 if (lpmcd
== NULL
|| lpmcd
->cbStruct
!= sizeof(*lpmcd
))
1135 return MMSYSERR_INVALPARAM
;
1137 sppaDetails
= (SEGPTR
)lpmcd
->paDetails
;
1138 lpmcd
->paDetails
= MapSL(sppaDetails
);
1139 ret
= mixerGetControlDetailsA(hmix
, (LPMIXERCONTROLDETAILS
)lpmcd
, fdwDetails
);
1140 lpmcd
->paDetails
= (LPVOID
)sppaDetails
;
1145 /**************************************************************************
1146 * mixerGetLineControlsA [WINMM.@]
1148 UINT WINAPI
mixerGetLineControlsA(HMIXEROBJ hmix
, LPMIXERLINECONTROLSA lpmlcA
,
1153 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmlcA
, fdwControls
);
1155 if ((lpwm
= MIXER_GetDev(hmix
, fdwControls
)) == NULL
)
1156 return MMSYSERR_INVALHANDLE
;
1158 if (lpmlcA
== NULL
|| lpmlcA
->cbStruct
!= sizeof(*lpmlcA
))
1159 return MMSYSERR_INVALPARAM
;
1161 return MMDRV_Message(&lpwm
->mld
, MXDM_GETLINECONTROLS
, (DWORD
)lpmlcA
,
1165 /**************************************************************************
1166 * mixerGetLineControlsW [WINMM.@]
1168 UINT WINAPI
mixerGetLineControlsW(HMIXEROBJ hmix
, LPMIXERLINECONTROLSW lpmlcW
,
1171 MIXERLINECONTROLSA mlcA
;
1175 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmlcW
, fdwControls
);
1177 if (lpmlcW
== NULL
|| lpmlcW
->cbStruct
!= sizeof(*lpmlcW
) ||
1178 lpmlcW
->cbmxctrl
!= sizeof(MIXERCONTROLW
))
1179 return MMSYSERR_INVALPARAM
;
1181 mlcA
.cbStruct
= sizeof(mlcA
);
1182 mlcA
.dwLineID
= lpmlcW
->dwLineID
;
1183 mlcA
.u
.dwControlID
= lpmlcW
->u
.dwControlID
;
1184 mlcA
.u
.dwControlType
= lpmlcW
->u
.dwControlType
;
1185 mlcA
.cControls
= lpmlcW
->cControls
;
1186 mlcA
.cbmxctrl
= sizeof(MIXERCONTROLA
);
1187 mlcA
.pamxctrl
= HeapAlloc(GetProcessHeap(), 0,
1188 mlcA
.cControls
* mlcA
.cbmxctrl
);
1190 ret
= mixerGetLineControlsA(hmix
, &mlcA
, fdwControls
);
1192 if (ret
== MMSYSERR_NOERROR
) {
1193 lpmlcW
->dwLineID
= mlcA
.dwLineID
;
1194 lpmlcW
->u
.dwControlID
= mlcA
.u
.dwControlID
;
1195 lpmlcW
->u
.dwControlType
= mlcA
.u
.dwControlType
;
1196 lpmlcW
->cControls
= mlcA
.cControls
;
1198 for (i
= 0; i
< mlcA
.cControls
; i
++) {
1199 lpmlcW
->pamxctrl
[i
].cbStruct
= sizeof(MIXERCONTROLW
);
1200 lpmlcW
->pamxctrl
[i
].dwControlID
= mlcA
.pamxctrl
[i
].dwControlID
;
1201 lpmlcW
->pamxctrl
[i
].dwControlType
= mlcA
.pamxctrl
[i
].dwControlType
;
1202 lpmlcW
->pamxctrl
[i
].fdwControl
= mlcA
.pamxctrl
[i
].fdwControl
;
1203 lpmlcW
->pamxctrl
[i
].cMultipleItems
= mlcA
.pamxctrl
[i
].cMultipleItems
;
1204 MultiByteToWideChar( CP_ACP
, 0, mlcA
.pamxctrl
[i
].szShortName
, -1,
1205 lpmlcW
->pamxctrl
[i
].szShortName
,
1206 sizeof(lpmlcW
->pamxctrl
[i
].szShortName
)/sizeof(WCHAR
) );
1207 MultiByteToWideChar( CP_ACP
, 0, mlcA
.pamxctrl
[i
].szName
, -1,
1208 lpmlcW
->pamxctrl
[i
].szName
,
1209 sizeof(lpmlcW
->pamxctrl
[i
].szName
)/sizeof(WCHAR
) );
1210 /* sizeof(lpmlcW->pamxctrl[i].Bounds) ==
1211 * sizeof(mlcA.pamxctrl[i].Bounds) */
1212 memcpy(&lpmlcW
->pamxctrl
[i
].Bounds
, &mlcA
.pamxctrl
[i
].Bounds
,
1213 sizeof(mlcA
.pamxctrl
[i
].Bounds
));
1214 /* sizeof(lpmlcW->pamxctrl[i].Metrics) ==
1215 * sizeof(mlcA.pamxctrl[i].Metrics) */
1216 memcpy(&lpmlcW
->pamxctrl
[i
].Metrics
, &mlcA
.pamxctrl
[i
].Metrics
,
1217 sizeof(mlcA
.pamxctrl
[i
].Metrics
));
1221 HeapFree(GetProcessHeap(), 0, mlcA
.pamxctrl
);
1226 /**************************************************************************
1227 * mixerGetLineControls [MMSYSTEM.807]
1229 UINT16 WINAPI
mixerGetLineControls16(HMIXEROBJ16 hmix
,
1230 LPMIXERLINECONTROLS16 lpmlc16
,
1233 MIXERLINECONTROLSA mlcA
;
1236 LPMIXERCONTROL16 lpmc16
;
1238 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmlc16
, fdwControls
);
1240 if (lpmlc16
== NULL
|| lpmlc16
->cbStruct
!= sizeof(*lpmlc16
) ||
1241 lpmlc16
->cbmxctrl
!= sizeof(MIXERCONTROL16
))
1242 return MMSYSERR_INVALPARAM
;
1244 mlcA
.cbStruct
= sizeof(mlcA
);
1245 mlcA
.dwLineID
= lpmlc16
->dwLineID
;
1246 mlcA
.u
.dwControlID
= lpmlc16
->u
.dwControlID
;
1247 mlcA
.u
.dwControlType
= lpmlc16
->u
.dwControlType
;
1248 mlcA
.cControls
= lpmlc16
->cControls
;
1249 mlcA
.cbmxctrl
= sizeof(MIXERCONTROLA
);
1250 mlcA
.pamxctrl
= HeapAlloc(GetProcessHeap(), 0,
1251 mlcA
.cControls
* mlcA
.cbmxctrl
);
1253 ret
= mixerGetLineControlsA(hmix
, &mlcA
, fdwControls
);
1255 if (ret
== MMSYSERR_NOERROR
) {
1256 lpmlc16
->dwLineID
= mlcA
.dwLineID
;
1257 lpmlc16
->u
.dwControlID
= mlcA
.u
.dwControlID
;
1258 lpmlc16
->u
.dwControlType
= mlcA
.u
.dwControlType
;
1259 lpmlc16
->cControls
= mlcA
.cControls
;
1261 lpmc16
= MapSL(lpmlc16
->pamxctrl
);
1263 for (i
= 0; i
< mlcA
.cControls
; i
++) {
1264 lpmc16
[i
].cbStruct
= sizeof(MIXERCONTROL16
);
1265 lpmc16
[i
].dwControlID
= mlcA
.pamxctrl
[i
].dwControlID
;
1266 lpmc16
[i
].dwControlType
= mlcA
.pamxctrl
[i
].dwControlType
;
1267 lpmc16
[i
].fdwControl
= mlcA
.pamxctrl
[i
].fdwControl
;
1268 lpmc16
[i
].cMultipleItems
= mlcA
.pamxctrl
[i
].cMultipleItems
;
1269 strcpy(lpmc16
[i
].szShortName
, mlcA
.pamxctrl
[i
].szShortName
);
1270 strcpy(lpmc16
[i
].szName
, mlcA
.pamxctrl
[i
].szName
);
1271 /* sizeof(lpmc16[i].Bounds) == sizeof(mlcA.pamxctrl[i].Bounds) */
1272 memcpy(&lpmc16
[i
].Bounds
, &mlcA
.pamxctrl
[i
].Bounds
,
1273 sizeof(mlcA
.pamxctrl
[i
].Bounds
));
1274 /* sizeof(lpmc16[i].Metrics) == sizeof(mlcA.pamxctrl[i].Metrics) */
1275 memcpy(&lpmc16
[i
].Metrics
, &mlcA
.pamxctrl
[i
].Metrics
,
1276 sizeof(mlcA
.pamxctrl
[i
].Metrics
));
1280 HeapFree(GetProcessHeap(), 0, mlcA
.pamxctrl
);
1285 /**************************************************************************
1286 * mixerGetLineInfoA [WINMM.@]
1288 UINT WINAPI
mixerGetLineInfoA(HMIXEROBJ hmix
, LPMIXERLINEA lpmliW
, DWORD fdwInfo
)
1292 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmliW
, fdwInfo
);
1294 if ((lpwm
= MIXER_GetDev(hmix
, fdwInfo
)) == NULL
)
1295 return MMSYSERR_INVALHANDLE
;
1297 return MMDRV_Message(&lpwm
->mld
, MXDM_GETLINEINFO
, (DWORD
)lpmliW
,
1301 /**************************************************************************
1302 * mixerGetLineInfoW [WINMM.@]
1304 UINT WINAPI
mixerGetLineInfoW(HMIXEROBJ hmix
, LPMIXERLINEW lpmliW
,
1310 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmliW
, fdwInfo
);
1312 if (lpmliW
== NULL
|| lpmliW
->cbStruct
!= sizeof(*lpmliW
))
1313 return MMSYSERR_INVALPARAM
;
1315 mliA
.cbStruct
= sizeof(mliA
);
1316 switch (fdwInfo
& MIXER_GETLINEINFOF_QUERYMASK
) {
1317 case MIXER_GETLINEINFOF_COMPONENTTYPE
:
1318 mliA
.dwComponentType
= lpmliW
->dwComponentType
;
1320 case MIXER_GETLINEINFOF_DESTINATION
:
1321 mliA
.dwDestination
= lpmliW
->dwDestination
;
1323 case MIXER_GETLINEINFOF_LINEID
:
1324 mliA
.dwLineID
= lpmliW
->dwLineID
;
1326 case MIXER_GETLINEINFOF_SOURCE
:
1327 mliA
.dwDestination
= lpmliW
->dwDestination
;
1328 mliA
.dwSource
= lpmliW
->dwSource
;
1330 case MIXER_GETLINEINFOF_TARGETTYPE
:
1331 mliA
.Target
.dwType
= lpmliW
->Target
.dwType
;
1332 mliA
.Target
.wMid
= lpmliW
->Target
.wMid
;
1333 mliA
.Target
.wPid
= lpmliW
->Target
.wPid
;
1334 mliA
.Target
.vDriverVersion
= lpmliW
->Target
.vDriverVersion
;
1335 WideCharToMultiByte( CP_ACP
, 0, lpmliW
->Target
.szPname
, -1, mliA
.Target
.szPname
, sizeof(mliA
.Target
.szPname
), NULL
, NULL
);
1338 FIXME("Unsupported fdwControls=0x%08lx\n", fdwInfo
);
1341 ret
= mixerGetLineInfoA(hmix
, &mliA
, fdwInfo
);
1343 lpmliW
->dwDestination
= mliA
.dwDestination
;
1344 lpmliW
->dwSource
= mliA
.dwSource
;
1345 lpmliW
->dwLineID
= mliA
.dwLineID
;
1346 lpmliW
->fdwLine
= mliA
.fdwLine
;
1347 lpmliW
->dwUser
= mliA
.dwUser
;
1348 lpmliW
->dwComponentType
= mliA
.dwComponentType
;
1349 lpmliW
->cChannels
= mliA
.cChannels
;
1350 lpmliW
->cConnections
= mliA
.cConnections
;
1351 lpmliW
->cControls
= mliA
.cControls
;
1352 MultiByteToWideChar( CP_ACP
, 0, mliA
.szShortName
, -1, lpmliW
->szShortName
,
1353 sizeof(lpmliW
->szShortName
)/sizeof(WCHAR
) );
1354 MultiByteToWideChar( CP_ACP
, 0, mliA
.szName
, -1, lpmliW
->szName
,
1355 sizeof(lpmliW
->szName
)/sizeof(WCHAR
) );
1356 lpmliW
->Target
.dwType
= mliA
.Target
.dwType
;
1357 lpmliW
->Target
.dwDeviceID
= mliA
.Target
.dwDeviceID
;
1358 lpmliW
->Target
.wMid
= mliA
.Target
.wMid
;
1359 lpmliW
->Target
.wPid
= mliA
.Target
.wPid
;
1360 lpmliW
->Target
.vDriverVersion
= mliA
.Target
.vDriverVersion
;
1361 MultiByteToWideChar( CP_ACP
, 0, mliA
.Target
.szPname
, -1, lpmliW
->Target
.szPname
,
1362 sizeof(lpmliW
->Target
.szPname
)/sizeof(WCHAR
) );
1367 /**************************************************************************
1368 * mixerGetLineInfo [MMSYSTEM.805]
1370 UINT16 WINAPI
mixerGetLineInfo16(HMIXEROBJ16 hmix
, LPMIXERLINE16 lpmli16
,
1376 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmli16
, fdwInfo
);
1378 if (lpmli16
== NULL
|| lpmli16
->cbStruct
!= sizeof(*lpmli16
))
1379 return MMSYSERR_INVALPARAM
;
1381 mliA
.cbStruct
= sizeof(mliA
);
1382 switch (fdwInfo
& MIXER_GETLINEINFOF_QUERYMASK
) {
1383 case MIXER_GETLINEINFOF_COMPONENTTYPE
:
1384 mliA
.dwComponentType
= lpmli16
->dwComponentType
;
1386 case MIXER_GETLINEINFOF_DESTINATION
:
1387 mliA
.dwDestination
= lpmli16
->dwDestination
;
1389 case MIXER_GETLINEINFOF_LINEID
:
1390 mliA
.dwLineID
= lpmli16
->dwLineID
;
1392 case MIXER_GETLINEINFOF_SOURCE
:
1393 mliA
.dwDestination
= lpmli16
->dwDestination
;
1394 mliA
.dwSource
= lpmli16
->dwSource
;
1396 case MIXER_GETLINEINFOF_TARGETTYPE
:
1397 mliA
.Target
.dwType
= lpmli16
->Target
.dwType
;
1398 mliA
.Target
.wMid
= lpmli16
->Target
.wMid
;
1399 mliA
.Target
.wPid
= lpmli16
->Target
.wPid
;
1400 mliA
.Target
.vDriverVersion
= lpmli16
->Target
.vDriverVersion
;
1401 strcpy(mliA
.Target
.szPname
, lpmli16
->Target
.szPname
);
1404 FIXME("Unsupported fdwControls=0x%08lx\n", fdwInfo
);
1407 ret
= mixerGetLineInfoA(hmix
, &mliA
, fdwInfo
);
1409 lpmli16
->dwDestination
= mliA
.dwDestination
;
1410 lpmli16
->dwSource
= mliA
.dwSource
;
1411 lpmli16
->dwLineID
= mliA
.dwLineID
;
1412 lpmli16
->fdwLine
= mliA
.fdwLine
;
1413 lpmli16
->dwUser
= mliA
.dwUser
;
1414 lpmli16
->dwComponentType
= mliA
.dwComponentType
;
1415 lpmli16
->cChannels
= mliA
.cChannels
;
1416 lpmli16
->cConnections
= mliA
.cConnections
;
1417 lpmli16
->cControls
= mliA
.cControls
;
1418 strcpy(lpmli16
->szShortName
, mliA
.szShortName
);
1419 strcpy(lpmli16
->szName
, mliA
.szName
);
1420 lpmli16
->Target
.dwType
= mliA
.Target
.dwType
;
1421 lpmli16
->Target
.dwDeviceID
= mliA
.Target
.dwDeviceID
;
1422 lpmli16
->Target
.wMid
= mliA
.Target
.wMid
;
1423 lpmli16
->Target
.wPid
= mliA
.Target
.wPid
;
1424 lpmli16
->Target
.vDriverVersion
= mliA
.Target
.vDriverVersion
;
1425 strcpy(lpmli16
->Target
.szPname
, mliA
.Target
.szPname
);
1430 /**************************************************************************
1431 * mixerSetControlDetails [WINMM.@]
1433 UINT WINAPI
mixerSetControlDetails(HMIXEROBJ hmix
, LPMIXERCONTROLDETAILS lpmcdA
,
1438 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcdA
, fdwDetails
);
1440 if ((lpwm
= MIXER_GetDev(hmix
, fdwDetails
)) == NULL
)
1441 return MMSYSERR_INVALHANDLE
;
1443 return MMDRV_Message(&lpwm
->mld
, MXDM_SETCONTROLDETAILS
, (DWORD
)lpmcdA
,
1447 /**************************************************************************
1448 * mixerSetControlDetails [MMSYSTEM.809]
1450 UINT16 WINAPI
mixerSetControlDetails16(HMIXEROBJ16 hmix
,
1451 LPMIXERCONTROLDETAILS16 lpmcd
,
1454 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcd
, fdwDetails
);
1455 return MMSYSERR_NOTENABLED
;
1458 /**************************************************************************
1459 * mixerMessage [WINMM.@]
1461 UINT WINAPI
mixerMessage(HMIXER hmix
, UINT uMsg
, DWORD dwParam1
, DWORD dwParam2
)
1465 TRACE("(%04lx, %d, %08lx, %08lx): semi-stub?\n",
1466 (DWORD
)hmix
, uMsg
, dwParam1
, dwParam2
);
1468 if ((wmld
= MMDRV_Get(hmix
, MMDRV_MIXER
, FALSE
)) == NULL
)
1469 return MMSYSERR_INVALHANDLE
;
1471 return MMDRV_Message(wmld
, uMsg
, dwParam1
, dwParam2
, TRUE
);
1474 /**************************************************************************
1475 * mixerMessage [MMSYSTEM.804]
1477 DWORD WINAPI
mixerMessage16(HMIXER16 hmix
, UINT16 uMsg
, DWORD dwParam1
,
1480 return mixerMessage(hmix
, uMsg
, dwParam1
, dwParam2
);
1483 /**************************************************************************
1484 * auxGetNumDevs [WINMM.@]
1486 UINT WINAPI
auxGetNumDevs(void)
1488 return MMDRV_GetNum(MMDRV_AUX
);
1491 /**************************************************************************
1492 * auxGetNumDevs [MMSYSTEM.350]
1494 UINT16 WINAPI
auxGetNumDevs16(void)
1496 return MMDRV_GetNum(MMDRV_AUX
);
1499 /**************************************************************************
1500 * auxGetDevCapsW [WINMM.@]
1502 UINT WINAPI
auxGetDevCapsW(UINT uDeviceID
, LPAUXCAPSW lpCaps
, UINT uSize
)
1505 UINT ret
= auxGetDevCapsA(uDeviceID
, &acA
, sizeof(acA
));
1507 lpCaps
->wMid
= acA
.wMid
;
1508 lpCaps
->wPid
= acA
.wPid
;
1509 lpCaps
->vDriverVersion
= acA
.vDriverVersion
;
1510 MultiByteToWideChar( CP_ACP
, 0, acA
.szPname
, -1, lpCaps
->szPname
,
1511 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
1512 lpCaps
->wTechnology
= acA
.wTechnology
;
1513 lpCaps
->dwSupport
= acA
.dwSupport
;
1517 /**************************************************************************
1518 * auxGetDevCapsA [WINMM.@]
1520 UINT WINAPI
auxGetDevCapsA(UINT uDeviceID
, LPAUXCAPSA lpCaps
, UINT uSize
)
1524 TRACE("(%04X, %p, %d) !\n", uDeviceID
, lpCaps
, uSize
);
1526 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1527 return MMSYSERR_INVALHANDLE
;
1528 return MMDRV_Message(wmld
, AUXDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
1531 /**************************************************************************
1532 * auxGetDevCaps [MMSYSTEM.351]
1534 UINT16 WINAPI
auxGetDevCaps16(UINT16 uDeviceID
, LPAUXCAPS16 lpCaps
, UINT16 uSize
)
1538 TRACE("(%04X, %p, %d) !\n", uDeviceID
, lpCaps
, uSize
);
1540 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1541 return MMSYSERR_INVALHANDLE
;
1542 return MMDRV_Message(wmld
, AUXDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
1545 /**************************************************************************
1546 * auxGetVolume [WINMM.@]
1548 UINT WINAPI
auxGetVolume(UINT uDeviceID
, DWORD
* lpdwVolume
)
1552 TRACE("(%04X, %p) !\n", uDeviceID
, lpdwVolume
);
1554 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1555 return MMSYSERR_INVALHANDLE
;
1556 return MMDRV_Message(wmld
, AUXDM_GETVOLUME
, (DWORD
)lpdwVolume
, 0L, TRUE
);
1559 /**************************************************************************
1560 * auxGetVolume [MMSYSTEM.352]
1562 UINT16 WINAPI
auxGetVolume16(UINT16 uDeviceID
, LPDWORD lpdwVolume
)
1566 TRACE("(%04X, %p) !\n", uDeviceID
, lpdwVolume
);
1568 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1569 return MMSYSERR_INVALHANDLE
;
1570 return MMDRV_Message(wmld
, AUXDM_GETVOLUME
, (DWORD
)lpdwVolume
, 0L, TRUE
);
1573 /**************************************************************************
1574 * auxSetVolume [WINMM.@]
1576 UINT WINAPI
auxSetVolume(UINT uDeviceID
, DWORD dwVolume
)
1580 TRACE("(%04X, %lu) !\n", uDeviceID
, dwVolume
);
1582 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1583 return MMSYSERR_INVALHANDLE
;
1584 return MMDRV_Message(wmld
, AUXDM_SETVOLUME
, dwVolume
, 0L, TRUE
);
1587 /**************************************************************************
1588 * auxSetVolume [MMSYSTEM.353]
1590 UINT16 WINAPI
auxSetVolume16(UINT16 uDeviceID
, DWORD dwVolume
)
1594 TRACE("(%04X, %lu) !\n", uDeviceID
, dwVolume
);
1596 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1597 return MMSYSERR_INVALHANDLE
;
1598 return MMDRV_Message(wmld
, AUXDM_SETVOLUME
, dwVolume
, 0L, TRUE
);
1601 /**************************************************************************
1602 * auxOutMessage [WINMM.@]
1604 DWORD WINAPI
auxOutMessage(UINT uDeviceID
, UINT uMessage
, DWORD dw1
, DWORD dw2
)
1608 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1609 return MMSYSERR_INVALHANDLE
;
1611 return MMDRV_Message(wmld
, uMessage
, dw1
, dw2
, TRUE
);
1614 /**************************************************************************
1615 * auxOutMessage [MMSYSTEM.354]
1617 DWORD WINAPI
auxOutMessage16(UINT16 uDeviceID
, UINT16 uMessage
, DWORD dw1
, DWORD dw2
)
1621 TRACE("(%04X, %04X, %08lX, %08lX)\n", uDeviceID
, uMessage
, dw1
, dw2
);
1624 case AUXDM_GETNUMDEVS
:
1625 case AUXDM_SETVOLUME
:
1626 /* no argument conversion needed */
1628 case AUXDM_GETVOLUME
:
1629 return auxGetVolume16(uDeviceID
, MapSL(dw1
));
1630 case AUXDM_GETDEVCAPS
:
1631 return auxGetDevCaps16(uDeviceID
, MapSL(dw1
), dw2
);
1633 TRACE("(%04x, %04x, %08lx, %08lx): unhandled message\n",
1634 uDeviceID
, uMessage
, dw1
, dw2
);
1637 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1638 return MMSYSERR_INVALHANDLE
;
1640 return MMDRV_Message(wmld
, uMessage
, dw1
, dw2
, TRUE
);
1643 /**************************************************************************
1644 * mciGetErrorStringW [WINMM.@]
1646 BOOL WINAPI
mciGetErrorStringW(DWORD wError
, LPWSTR lpstrBuffer
, UINT uLength
)
1648 LPSTR bufstr
= HeapAlloc(GetProcessHeap(), 0, uLength
);
1649 BOOL ret
= mciGetErrorStringA(wError
, bufstr
, uLength
);
1651 MultiByteToWideChar( CP_ACP
, 0, bufstr
, -1, lpstrBuffer
, uLength
);
1652 HeapFree(GetProcessHeap(), 0, bufstr
);
1656 /**************************************************************************
1657 * mciGetErrorString [MMSYSTEM.706]
1659 BOOL16 WINAPI
mciGetErrorString16(DWORD wError
, LPSTR lpstrBuffer
, UINT16 uLength
)
1661 return mciGetErrorStringA(wError
, lpstrBuffer
, uLength
);
1664 /**************************************************************************
1665 * mciGetErrorStringA [WINMM.@]
1667 BOOL WINAPI
mciGetErrorStringA(DWORD dwError
, LPSTR lpstrBuffer
, UINT uLength
)
1671 if (lpstrBuffer
!= NULL
&& uLength
> 0 &&
1672 dwError
>= MCIERR_BASE
&& dwError
<= MCIERR_CUSTOM_DRIVER_BASE
) {
1674 if (LoadStringA(MULTIMEDIA_GetIData()->hWinMM32Instance
,
1675 dwError
, lpstrBuffer
, uLength
) > 0) {
1682 /**************************************************************************
1683 * mciDriverNotify [MMSYSTEM.711]
1685 BOOL16 WINAPI
mciDriverNotify16(HWND16 hWndCallBack
, UINT16 wDevID
, UINT16 wStatus
)
1687 TRACE("(%04X, %04x, %04X)\n", hWndCallBack
, wDevID
, wStatus
);
1689 return PostMessageA(hWndCallBack
, MM_MCINOTIFY
, wStatus
, wDevID
);
1692 /**************************************************************************
1693 * mciDriverNotify [WINMM.@]
1695 BOOL WINAPI
mciDriverNotify(HWND hWndCallBack
, UINT wDevID
, UINT wStatus
)
1698 TRACE("(%08X, %04x, %04X)\n", hWndCallBack
, wDevID
, wStatus
);
1700 return PostMessageA(hWndCallBack
, MM_MCINOTIFY
, wStatus
, wDevID
);
1703 /**************************************************************************
1704 * mciGetDriverData [MMSYSTEM.708]
1706 DWORD WINAPI
mciGetDriverData16(UINT16 uDeviceID
)
1708 return mciGetDriverData(uDeviceID
);
1711 /**************************************************************************
1712 * mciGetDriverData [WINMM.@]
1714 DWORD WINAPI
mciGetDriverData(UINT uDeviceID
)
1716 LPWINE_MCIDRIVER wmd
;
1718 TRACE("(%04x)\n", uDeviceID
);
1720 wmd
= MCI_GetDriver(uDeviceID
);
1723 WARN("Bad uDeviceID\n");
1727 return wmd
->dwPrivate
;
1730 /**************************************************************************
1731 * mciSetDriverData [MMSYSTEM.707]
1733 BOOL16 WINAPI
mciSetDriverData16(UINT16 uDeviceID
, DWORD data
)
1735 return mciSetDriverData(uDeviceID
, data
);
1738 /**************************************************************************
1739 * mciSetDriverData [WINMM.@]
1741 BOOL WINAPI
mciSetDriverData(UINT uDeviceID
, DWORD data
)
1743 LPWINE_MCIDRIVER wmd
;
1745 TRACE("(%04x, %08lx)\n", uDeviceID
, data
);
1747 wmd
= MCI_GetDriver(uDeviceID
);
1750 WARN("Bad uDeviceID\n");
1754 wmd
->dwPrivate
= data
;
1758 /**************************************************************************
1759 * mciSendCommandA [WINMM.@]
1761 DWORD WINAPI
mciSendCommandA(UINT wDevID
, UINT wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1765 TRACE("(%08x, %s, %08lx, %08lx)\n",
1766 wDevID
, MCI_MessageToString(wMsg
), dwParam1
, dwParam2
);
1768 dwRet
= MCI_SendCommand(wDevID
, wMsg
, dwParam1
, dwParam2
, TRUE
);
1769 dwRet
= MCI_CleanUp(dwRet
, wMsg
, dwParam2
, TRUE
);
1770 TRACE("=> %08lx\n", dwRet
);
1774 /**************************************************************************
1775 * mciSendCommandW [WINMM.@]
1777 DWORD WINAPI
mciSendCommandW(UINT wDevID
, UINT wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1779 FIXME("(%08x, %s, %08lx, %08lx): stub\n",
1780 wDevID
, MCI_MessageToString(wMsg
), dwParam1
, dwParam2
);
1781 return MCIERR_UNSUPPORTED_FUNCTION
;
1784 /**************************************************************************
1785 * mciSendCommand [MMSYSTEM.701]
1787 DWORD WINAPI
mciSendCommand16(UINT16 wDevID
, UINT16 wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1791 TRACE("(%04X, %s, %08lX, %08lX)\n",
1792 wDevID
, MCI_MessageToString(wMsg
), dwParam1
, dwParam2
);
1794 dwRet
= MCI_SendCommand(wDevID
, wMsg
, dwParam1
, dwParam2
, FALSE
);
1795 dwRet
= MCI_CleanUp(dwRet
, wMsg
, dwParam2
, FALSE
);
1796 TRACE("=> %ld\n", dwRet
);
1800 /**************************************************************************
1801 * mciGetDeviceID [MMSYSTEM.703]
1803 UINT16 WINAPI
mciGetDeviceID16(LPCSTR lpstrName
)
1805 TRACE("(\"%s\")\n", lpstrName
);
1807 return MCI_GetDriverFromString(lpstrName
);
1810 /**************************************************************************
1811 * mciGetDeviceIDA [WINMM.@]
1813 UINT WINAPI
mciGetDeviceIDA(LPCSTR lpstrName
)
1815 return MCI_GetDriverFromString(lpstrName
);
1818 /**************************************************************************
1819 * mciGetDeviceIDW [WINMM.@]
1821 UINT WINAPI
mciGetDeviceIDW(LPCWSTR lpwstrName
)
1826 lpstrName
= HEAP_strdupWtoA(GetProcessHeap(), 0, lpwstrName
);
1827 ret
= MCI_GetDriverFromString(lpstrName
);
1828 HeapFree(GetProcessHeap(), 0, lpstrName
);
1832 /**************************************************************************
1833 * MCI_DefYieldProc [internal]
1835 UINT WINAPI
MCI_DefYieldProc(MCIDEVICEID wDevID
, DWORD data
)
1839 TRACE("(0x%04x, 0x%08lx)\n", wDevID
, data
);
1841 if ((HIWORD(data
) != 0 && GetActiveWindow() != HIWORD(data
)) ||
1842 (GetAsyncKeyState(LOWORD(data
)) & 1) == 0) {
1848 msg
.hwnd
= HIWORD(data
);
1849 while (!PeekMessageA(&msg
, HIWORD(data
), WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
));
1855 /**************************************************************************
1856 * mciSetYieldProc [MMSYSTEM.714]
1858 BOOL16 WINAPI
mciSetYieldProc16(UINT16 uDeviceID
, YIELDPROC16 fpYieldProc
, DWORD dwYieldData
)
1860 LPWINE_MCIDRIVER wmd
;
1862 TRACE("(%u, %p, %08lx)\n", uDeviceID
, fpYieldProc
, dwYieldData
);
1864 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
1865 WARN("Bad uDeviceID\n");
1869 wmd
->lpfnYieldProc
= (YIELDPROC
)fpYieldProc
;
1870 wmd
->dwYieldData
= dwYieldData
;
1876 /**************************************************************************
1877 * mciSetYieldProc [WINMM.@]
1879 BOOL WINAPI
mciSetYieldProc(UINT uDeviceID
, YIELDPROC fpYieldProc
, DWORD dwYieldData
)
1881 LPWINE_MCIDRIVER wmd
;
1883 TRACE("(%u, %p, %08lx)\n", uDeviceID
, fpYieldProc
, dwYieldData
);
1885 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
1886 WARN("Bad uDeviceID\n");
1890 wmd
->lpfnYieldProc
= fpYieldProc
;
1891 wmd
->dwYieldData
= dwYieldData
;
1897 /**************************************************************************
1898 * mciGetDeviceIDFromElementID [MMSYSTEM.715]
1900 UINT16 WINAPI
mciGetDeviceIDFromElementID16(DWORD dwElementID
, LPCSTR lpstrType
)
1902 FIXME("(%lu, %s) stub\n", dwElementID
, lpstrType
);
1906 /**************************************************************************
1907 * mciGetDeviceIDFromElementIDW [WINMM.@]
1909 UINT WINAPI
mciGetDeviceIDFromElementIDW(DWORD dwElementID
, LPCWSTR lpstrType
)
1911 /* FIXME: that's rather strange, there is no
1912 * mciGetDeviceIDFromElementID32A in winmm.spec
1914 FIXME("(%lu, %p) stub\n", dwElementID
, lpstrType
);
1918 /**************************************************************************
1919 * mciGetYieldProc [MMSYSTEM.716]
1921 YIELDPROC16 WINAPI
mciGetYieldProc16(UINT16 uDeviceID
, DWORD
* lpdwYieldData
)
1923 LPWINE_MCIDRIVER wmd
;
1925 TRACE("(%u, %p)\n", uDeviceID
, lpdwYieldData
);
1927 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
1928 WARN("Bad uDeviceID\n");
1931 if (!wmd
->lpfnYieldProc
) {
1932 WARN("No proc set\n");
1936 WARN("Proc is 32 bit\n");
1939 return (YIELDPROC16
)wmd
->lpfnYieldProc
;
1942 /**************************************************************************
1943 * mciGetYieldProc [WINMM.@]
1945 YIELDPROC WINAPI
mciGetYieldProc(UINT uDeviceID
, DWORD
* lpdwYieldData
)
1947 LPWINE_MCIDRIVER wmd
;
1949 TRACE("(%u, %p)\n", uDeviceID
, lpdwYieldData
);
1951 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
1952 WARN("Bad uDeviceID\n");
1955 if (!wmd
->lpfnYieldProc
) {
1956 WARN("No proc set\n");
1960 WARN("Proc is 32 bit\n");
1963 return wmd
->lpfnYieldProc
;
1966 /**************************************************************************
1967 * mciGetCreatorTask [MMSYSTEM.717]
1969 HTASK16 WINAPI
mciGetCreatorTask16(UINT16 uDeviceID
)
1971 return mciGetCreatorTask(uDeviceID
);
1974 /**************************************************************************
1975 * mciGetCreatorTask [WINMM.@]
1977 HTASK WINAPI
mciGetCreatorTask(UINT uDeviceID
)
1979 LPWINE_MCIDRIVER wmd
;
1982 TRACE("(%u)\n", uDeviceID
);
1984 ret
= (!(wmd
= MCI_GetDriver(uDeviceID
))) ? 0 : wmd
->hCreatorTask
;
1986 TRACE("=> %04x\n", ret
);
1990 /**************************************************************************
1991 * mciDriverYield [MMSYSTEM.710]
1993 UINT16 WINAPI
mciDriverYield16(UINT16 uDeviceID
)
1995 LPWINE_MCIDRIVER wmd
;
1998 /* TRACE("(%04x)\n", uDeviceID); */
2000 if (!(wmd
= MCI_GetDriver(uDeviceID
)) || !wmd
->lpfnYieldProc
|| wmd
->bIs32
) {
2003 ret
= wmd
->lpfnYieldProc(uDeviceID
, wmd
->dwYieldData
);
2009 /**************************************************************************
2010 * mciDriverYield [WINMM.@]
2012 UINT WINAPI
mciDriverYield(UINT uDeviceID
)
2014 LPWINE_MCIDRIVER wmd
;
2017 TRACE("(%04x)\n", uDeviceID
);
2019 if (!(wmd
= MCI_GetDriver(uDeviceID
)) || !wmd
->lpfnYieldProc
|| !wmd
->bIs32
) {
2022 ret
= wmd
->lpfnYieldProc(uDeviceID
, wmd
->dwYieldData
);
2028 /**************************************************************************
2029 * midiOutGetNumDevs [WINMM.@]
2031 UINT WINAPI
midiOutGetNumDevs(void)
2033 return MMDRV_GetNum(MMDRV_MIDIOUT
);
2036 /**************************************************************************
2037 * midiOutGetNumDevs [MMSYSTEM.201]
2039 UINT16 WINAPI
midiOutGetNumDevs16(void)
2041 return MMDRV_GetNum(MMDRV_MIDIOUT
);
2044 /**************************************************************************
2045 * midiOutGetDevCapsW [WINMM.@]
2047 UINT WINAPI
midiOutGetDevCapsW(UINT uDeviceID
, LPMIDIOUTCAPSW lpCaps
,
2053 ret
= midiOutGetDevCapsA(uDeviceID
, &mocA
, sizeof(mocA
));
2054 lpCaps
->wMid
= mocA
.wMid
;
2055 lpCaps
->wPid
= mocA
.wPid
;
2056 lpCaps
->vDriverVersion
= mocA
.vDriverVersion
;
2057 MultiByteToWideChar( CP_ACP
, 0, mocA
.szPname
, -1, lpCaps
->szPname
,
2058 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
2059 lpCaps
->wTechnology
= mocA
.wTechnology
;
2060 lpCaps
->wVoices
= mocA
.wVoices
;
2061 lpCaps
->wNotes
= mocA
.wNotes
;
2062 lpCaps
->wChannelMask
= mocA
.wChannelMask
;
2063 lpCaps
->dwSupport
= mocA
.dwSupport
;
2067 /**************************************************************************
2068 * midiOutGetDevCapsA [WINMM.@]
2070 UINT WINAPI
midiOutGetDevCapsA(UINT uDeviceID
, LPMIDIOUTCAPSA lpCaps
,
2075 TRACE("(%u, %p, %u);\n", uDeviceID
, lpCaps
, uSize
);
2077 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
2079 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_MIDIOUT
, TRUE
)) == NULL
)
2080 return MMSYSERR_INVALHANDLE
;
2082 return MMDRV_Message(wmld
, MODM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
2085 /**************************************************************************
2086 * midiOutGetDevCaps [MMSYSTEM.202]
2088 UINT16 WINAPI
midiOutGetDevCaps16(UINT16 uDeviceID
, LPMIDIOUTCAPS16 lpCaps
,
2094 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
2096 dwRet
= midiOutGetDevCapsA(uDeviceID
, &capsA
, sizeof(capsA
));
2097 if (dwRet
== MMSYSERR_NOERROR
) {
2098 lpCaps
->wMid
= capsA
.wMid
;
2099 lpCaps
->wPid
= capsA
.wPid
;
2100 lpCaps
->vDriverVersion
= capsA
.vDriverVersion
;
2101 strcpy(lpCaps
->szPname
, capsA
.szPname
);
2102 lpCaps
->wTechnology
= capsA
.wTechnology
;
2103 lpCaps
->wVoices
= capsA
.wVoices
;
2104 lpCaps
->wNotes
= capsA
.wNotes
;
2105 lpCaps
->wChannelMask
= capsA
.wChannelMask
;
2106 lpCaps
->dwSupport
= capsA
.dwSupport
;
2111 /**************************************************************************
2112 * MIDI_GetErrorText [internal]
2114 static UINT16
MIDI_GetErrorText(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
2116 UINT16 ret
= MMSYSERR_BADERRNUM
;
2118 if (lpText
== NULL
) {
2119 ret
= MMSYSERR_INVALPARAM
;
2120 } else if (uSize
== 0) {
2121 ret
= MMSYSERR_NOERROR
;
2123 /* test has been removed 'coz MMSYSERR_BASE is 0, and gcc did emit
2124 * a warning for the test was always true */
2125 (/*uError >= MMSYSERR_BASE && */ uError
<= MMSYSERR_LASTERROR
) ||
2126 (uError
>= MIDIERR_BASE
&& uError
<= MIDIERR_LASTERROR
)) {
2128 if (LoadStringA(MULTIMEDIA_GetIData()->hWinMM32Instance
,
2129 uError
, lpText
, uSize
) > 0) {
2130 ret
= MMSYSERR_NOERROR
;
2136 /**************************************************************************
2137 * midiOutGetErrorTextA [WINMM.@]
2139 UINT WINAPI
midiOutGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
2141 return MIDI_GetErrorText(uError
, lpText
, uSize
);
2144 /**************************************************************************
2145 * midiOutGetErrorTextW [WINMM.@]
2147 UINT WINAPI
midiOutGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
2149 LPSTR xstr
= HeapAlloc(GetProcessHeap(), 0, uSize
);
2152 ret
= MIDI_GetErrorText(uError
, xstr
, uSize
);
2153 MultiByteToWideChar( CP_ACP
, 0, xstr
, -1, lpText
, uSize
);
2154 HeapFree(GetProcessHeap(), 0, xstr
);
2158 /**************************************************************************
2159 * midiOutGetErrorText [MMSYSTEM.203]
2161 UINT16 WINAPI
midiOutGetErrorText16(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
2163 return MIDI_GetErrorText(uError
, lpText
, uSize
);
2166 /**************************************************************************
2167 * MIDI_OutAlloc [internal]
2169 static LPWINE_MIDI
MIDI_OutAlloc(HMIDIOUT
* lphMidiOut
, LPDWORD lpdwCallback
,
2170 LPDWORD lpdwInstance
, LPDWORD lpdwFlags
,
2171 DWORD cIDs
, MIDIOPENSTRMID
* lpIDs
, BOOL bFrom32
)
2177 size
= sizeof(WINE_MIDI
) + (cIDs
? (cIDs
-1) : 0) * sizeof(MIDIOPENSTRMID
);
2179 lpwm
= (LPWINE_MIDI
)MMDRV_Alloc(size
, MMDRV_MIDIOUT
, &hMidiOut
, lpdwFlags
,
2180 lpdwCallback
, lpdwInstance
, bFrom32
);
2182 if (lphMidiOut
!= NULL
)
2183 *lphMidiOut
= hMidiOut
;
2186 lpwm
->mod
.hMidi
= hMidiOut
;
2187 lpwm
->mod
.dwCallback
= *lpdwCallback
;
2188 lpwm
->mod
.dwInstance
= *lpdwInstance
;
2189 lpwm
->mod
.dnDevNode
= 0;
2190 lpwm
->mod
.cIds
= cIDs
;
2192 memcpy(&(lpwm
->mod
.rgIds
), lpIDs
, cIDs
* sizeof(MIDIOPENSTRMID
));
2197 UINT
MMSYSTEM_midiOutOpen(HMIDIOUT
* lphMidiOut
, UINT uDeviceID
, DWORD dwCallback
,
2198 DWORD dwInstance
, DWORD dwFlags
, BOOL bFrom32
)
2204 TRACE("(%p, %d, %08lX, %08lX, %08lX);\n",
2205 lphMidiOut
, uDeviceID
, dwCallback
, dwInstance
, dwFlags
);
2207 if (lphMidiOut
!= NULL
) *lphMidiOut
= 0;
2209 lpwm
= MIDI_OutAlloc(&hMidiOut
, &dwCallback
, &dwInstance
, &dwFlags
,
2213 return MMSYSERR_NOMEM
;
2215 lpwm
->mld
.uDeviceID
= uDeviceID
;
2217 dwRet
= MMDRV_Open((LPWINE_MLD
)lpwm
, MODM_OPEN
, (DWORD
)&lpwm
->mod
,
2220 if (dwRet
!= MMSYSERR_NOERROR
) {
2221 MMDRV_Free(hMidiOut
, (LPWINE_MLD
)lpwm
);
2225 if (lphMidiOut
) *lphMidiOut
= hMidiOut
;
2226 TRACE("=> %d hMidi=%04x\n", dwRet
, hMidiOut
);
2231 /**************************************************************************
2232 * midiOutOpen [WINMM.@]
2234 UINT WINAPI
midiOutOpen(HMIDIOUT
* lphMidiOut
, UINT uDeviceID
,
2235 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
2237 return MMSYSTEM_midiOutOpen(lphMidiOut
, uDeviceID
, dwCallback
,
2238 dwInstance
, dwFlags
, TRUE
);
2241 /**************************************************************************
2242 * midiOutOpen [MMSYSTEM.204]
2244 UINT16 WINAPI
midiOutOpen16(HMIDIOUT16
* lphMidiOut
, UINT16 uDeviceID
,
2245 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
2250 ret
= MMSYSTEM_midiOutOpen(&hmo
, uDeviceID
, dwCallback
, dwInstance
,
2253 if (lphMidiOut
!= NULL
) *lphMidiOut
= hmo
;
2257 /**************************************************************************
2258 * midiOutClose [WINMM.@]
2260 UINT WINAPI
midiOutClose(HMIDIOUT hMidiOut
)
2265 TRACE("(%04X)\n", hMidiOut
);
2267 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2268 return MMSYSERR_INVALHANDLE
;
2270 dwRet
= MMDRV_Close(wmld
, MODM_CLOSE
);
2271 MMDRV_Free(hMidiOut
, wmld
);
2276 /**************************************************************************
2277 * midiOutClose [MMSYSTEM.205]
2279 UINT16 WINAPI
midiOutClose16(HMIDIOUT16 hMidiOut
)
2281 return midiOutClose(hMidiOut
);
2284 /**************************************************************************
2285 * midiOutPrepareHeader [WINMM.@]
2287 UINT WINAPI
midiOutPrepareHeader(HMIDIOUT hMidiOut
,
2288 MIDIHDR
* lpMidiOutHdr
, UINT uSize
)
2292 TRACE("(%04X, %p, %d)\n", hMidiOut
, lpMidiOutHdr
, uSize
);
2294 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2295 return MMSYSERR_INVALHANDLE
;
2297 return MMDRV_Message(wmld
, MODM_PREPARE
, (DWORD
)lpMidiOutHdr
, uSize
, TRUE
);
2300 /**************************************************************************
2301 * midiOutPrepareHeader [MMSYSTEM.206]
2303 UINT16 WINAPI
midiOutPrepareHeader16(HMIDIOUT16 hMidiOut
, /* [in] */
2304 SEGPTR lpsegMidiOutHdr
, /* [???] */
2305 UINT16 uSize
) /* [in] */
2309 TRACE("(%04X, %08lx, %d)\n", hMidiOut
, lpsegMidiOutHdr
, uSize
);
2311 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2312 return MMSYSERR_INVALHANDLE
;
2314 return MMDRV_Message(wmld
, MODM_PREPARE
, lpsegMidiOutHdr
, uSize
, FALSE
);
2317 /**************************************************************************
2318 * midiOutUnprepareHeader [WINMM.@]
2320 UINT WINAPI
midiOutUnprepareHeader(HMIDIOUT hMidiOut
,
2321 MIDIHDR
* lpMidiOutHdr
, UINT uSize
)
2325 TRACE("(%04X, %p, %d)\n", hMidiOut
, lpMidiOutHdr
, uSize
);
2327 if (!(lpMidiOutHdr
->dwFlags
& MHDR_PREPARED
)) {
2328 return MMSYSERR_NOERROR
;
2331 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2332 return MMSYSERR_INVALHANDLE
;
2334 return MMDRV_Message(wmld
, MODM_UNPREPARE
, (DWORD
)lpMidiOutHdr
, uSize
, TRUE
);
2337 /**************************************************************************
2338 * midiOutUnprepareHeader [MMSYSTEM.207]
2340 UINT16 WINAPI
midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut
, /* [in] */
2341 SEGPTR lpsegMidiOutHdr
, /* [???] */
2342 UINT16 uSize
) /* [in] */
2345 LPMIDIHDR16 lpMidiOutHdr
= MapSL(lpsegMidiOutHdr
);
2347 TRACE("(%04X, %08lx, %d)\n", hMidiOut
, lpsegMidiOutHdr
, uSize
);
2349 if (!(lpMidiOutHdr
->dwFlags
& MHDR_PREPARED
)) {
2350 return MMSYSERR_NOERROR
;
2353 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2354 return MMSYSERR_INVALHANDLE
;
2356 return MMDRV_Message(wmld
, MODM_UNPREPARE
, (DWORD
)lpsegMidiOutHdr
, uSize
, FALSE
);
2359 /**************************************************************************
2360 * midiOutShortMsg [WINMM.@]
2362 UINT WINAPI
midiOutShortMsg(HMIDIOUT hMidiOut
, DWORD dwMsg
)
2366 TRACE("(%04X, %08lX)\n", hMidiOut
, dwMsg
);
2368 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2369 return MMSYSERR_INVALHANDLE
;
2371 return MMDRV_Message(wmld
, MODM_DATA
, dwMsg
, 0L, FALSE
);
2374 /**************************************************************************
2375 * midiOutShortMsg [MMSYSTEM.208]
2377 UINT16 WINAPI
midiOutShortMsg16(HMIDIOUT16 hMidiOut
, DWORD dwMsg
)
2379 return midiOutShortMsg(hMidiOut
, dwMsg
);
2382 /**************************************************************************
2383 * midiOutLongMsg [WINMM.@]
2385 UINT WINAPI
midiOutLongMsg(HMIDIOUT hMidiOut
,
2386 MIDIHDR
* lpMidiOutHdr
, UINT uSize
)
2390 TRACE("(%04X, %p, %d)\n", hMidiOut
, lpMidiOutHdr
, uSize
);
2392 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2393 return MMSYSERR_INVALHANDLE
;
2395 return MMDRV_Message(wmld
, MODM_LONGDATA
, (DWORD
)lpMidiOutHdr
, uSize
, TRUE
);
2398 /**************************************************************************
2399 * midiOutLongMsg [MMSYSTEM.209]
2401 UINT16 WINAPI
midiOutLongMsg16(HMIDIOUT16 hMidiOut
, /* [in] */
2402 LPMIDIHDR16 lpsegMidiOutHdr
, /* [???] NOTE: SEGPTR */
2403 UINT16 uSize
) /* [in] */
2407 TRACE("(%04X, %p, %d)\n", hMidiOut
, lpsegMidiOutHdr
, uSize
);
2409 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2410 return MMSYSERR_INVALHANDLE
;
2412 return MMDRV_Message(wmld
, MODM_LONGDATA
, (DWORD
)lpsegMidiOutHdr
, uSize
, FALSE
);
2415 /**************************************************************************
2416 * midiOutReset [WINMM.@]
2418 UINT WINAPI
midiOutReset(HMIDIOUT hMidiOut
)
2422 TRACE("(%04X)\n", hMidiOut
);
2424 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2425 return MMSYSERR_INVALHANDLE
;
2427 return MMDRV_Message(wmld
, MODM_RESET
, 0L, 0L, TRUE
);
2430 /**************************************************************************
2431 * midiOutReset [MMSYSTEM.210]
2433 UINT16 WINAPI
midiOutReset16(HMIDIOUT16 hMidiOut
)
2435 return midiOutReset(hMidiOut
);
2438 /**************************************************************************
2439 * midiOutGetVolume [WINMM.@]
2441 UINT WINAPI
midiOutGetVolume(UINT uDeviceID
, DWORD
* lpdwVolume
)
2445 TRACE("(%04X, %p);\n", uDeviceID
, lpdwVolume
);
2447 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_MIDIOUT
, TRUE
)) == NULL
)
2448 return MMSYSERR_INVALHANDLE
;
2450 return MMDRV_Message(wmld
, MODM_GETVOLUME
, (DWORD
)lpdwVolume
, 0L, TRUE
);
2453 /**************************************************************************
2454 * midiOutGetVolume [MMSYSTEM.211]
2456 UINT16 WINAPI
midiOutGetVolume16(UINT16 uDeviceID
, DWORD
* lpdwVolume
)
2458 return midiOutGetVolume(uDeviceID
, lpdwVolume
);
2461 /**************************************************************************
2462 * midiOutSetVolume [WINMM.@]
2464 UINT WINAPI
midiOutSetVolume(UINT uDeviceID
, DWORD dwVolume
)
2468 TRACE("(%04X, %ld);\n", uDeviceID
, dwVolume
);
2470 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_MIDIOUT
, TRUE
)) == NULL
)
2471 return MMSYSERR_INVALHANDLE
;
2473 return MMDRV_Message(wmld
, MODM_SETVOLUME
, dwVolume
, 0L, TRUE
);
2476 /**************************************************************************
2477 * midiOutSetVolume [MMSYSTEM.212]
2479 UINT16 WINAPI
midiOutSetVolume16(UINT16 uDeviceID
, DWORD dwVolume
)
2481 return midiOutSetVolume(uDeviceID
, dwVolume
);
2484 /**************************************************************************
2485 * midiOutCachePatches [WINMM.@]
2487 UINT WINAPI
midiOutCachePatches(HMIDIOUT hMidiOut
, UINT uBank
,
2488 WORD
* lpwPatchArray
, UINT uFlags
)
2490 /* not really necessary to support this */
2491 FIXME("not supported yet\n");
2492 return MMSYSERR_NOTSUPPORTED
;
2495 /**************************************************************************
2496 * midiOutCachePatches [MMSYSTEM.213]
2498 UINT16 WINAPI
midiOutCachePatches16(HMIDIOUT16 hMidiOut
, UINT16 uBank
,
2499 WORD
* lpwPatchArray
, UINT16 uFlags
)
2501 return midiOutCachePatches(hMidiOut
, uBank
, lpwPatchArray
, uFlags
);
2504 /**************************************************************************
2505 * midiOutCacheDrumPatches [WINMM.@]
2507 UINT WINAPI
midiOutCacheDrumPatches(HMIDIOUT hMidiOut
, UINT uPatch
,
2508 WORD
* lpwKeyArray
, UINT uFlags
)
2510 FIXME("not supported yet\n");
2511 return MMSYSERR_NOTSUPPORTED
;
2514 /**************************************************************************
2515 * midiOutCacheDrumPatches [MMSYSTEM.214]
2517 UINT16 WINAPI
midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut
, UINT16 uPatch
,
2518 WORD
* lpwKeyArray
, UINT16 uFlags
)
2520 return midiOutCacheDrumPatches16(hMidiOut
, uPatch
, lpwKeyArray
, uFlags
);
2523 /**************************************************************************
2524 * midiOutGetID [WINMM.@]
2526 UINT WINAPI
midiOutGetID(HMIDIOUT hMidiOut
, UINT
* lpuDeviceID
)
2530 TRACE("(%04X, %p)\n", hMidiOut
, lpuDeviceID
);
2532 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
2533 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2534 return MMSYSERR_INVALHANDLE
;
2536 *lpuDeviceID
= wmld
->uDeviceID
;
2537 return MMSYSERR_NOERROR
;
2540 /**************************************************************************
2541 * midiOutGetID [MMSYSTEM.215]
2543 UINT16 WINAPI
midiOutGetID16(HMIDIOUT16 hMidiOut
, UINT16
* lpuDeviceID
)
2547 TRACE("(%04X, %p)\n", hMidiOut
, lpuDeviceID
);
2549 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
2550 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2551 return MMSYSERR_INVALHANDLE
;
2553 *lpuDeviceID
= wmld
->uDeviceID
;
2554 return MMSYSERR_NOERROR
;
2557 /**************************************************************************
2558 * midiOutMessage [WINMM.@]
2560 DWORD WINAPI
midiOutMessage(HMIDIOUT hMidiOut
, UINT uMessage
,
2561 DWORD dwParam1
, DWORD dwParam2
)
2565 TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiOut
, uMessage
, dwParam1
, dwParam2
);
2567 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
) {
2569 if (uMessage
== 0x0001) {
2570 *(LPDWORD
)dwParam1
= 1;
2573 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, TRUE
)) != NULL
) {
2574 return MMDRV_PhysicalFeatures(wmld
, uMessage
, dwParam1
, dwParam2
);
2576 return MMSYSERR_INVALHANDLE
;
2582 FIXME("can't handle OPEN or CLOSE message!\n");
2583 return MMSYSERR_NOTSUPPORTED
;
2585 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
2588 /**************************************************************************
2589 * midiOutMessage [MMSYSTEM.216]
2591 DWORD WINAPI
midiOutMessage16(HMIDIOUT16 hMidiOut
, UINT16 uMessage
,
2592 DWORD dwParam1
, DWORD dwParam2
)
2596 TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiOut
, uMessage
, dwParam1
, dwParam2
);
2598 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2599 return MMSYSERR_INVALHANDLE
;
2604 FIXME("can't handle OPEN or CLOSE message!\n");
2605 return MMSYSERR_NOTSUPPORTED
;
2607 case MODM_GETVOLUME
:
2608 return midiOutGetVolume16(hMidiOut
, MapSL(dwParam1
));
2610 return midiOutLongMsg16(hMidiOut
, MapSL(dwParam1
), dwParam2
);
2612 /* lpMidiOutHdr is still a segmented pointer for this function */
2613 return midiOutPrepareHeader16(hMidiOut
, dwParam1
, dwParam2
);
2614 case MODM_UNPREPARE
:
2615 return midiOutUnprepareHeader16(hMidiOut
, dwParam1
, dwParam2
);
2617 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
2620 /**************************************************************************
2621 * midiInGetNumDevs [WINMM.@]
2623 UINT WINAPI
midiInGetNumDevs(void)
2625 return MMDRV_GetNum(MMDRV_MIDIIN
);
2628 /**************************************************************************
2629 * midiInGetNumDevs [MMSYSTEM.301]
2631 UINT16 WINAPI
midiInGetNumDevs16(void)
2633 return MMDRV_GetNum(MMDRV_MIDIIN
);
2636 /**************************************************************************
2637 * midiInGetDevCapsW [WINMM.@]
2639 UINT WINAPI
midiInGetDevCapsW(UINT uDeviceID
, LPMIDIINCAPSW lpCaps
, UINT uSize
)
2642 UINT ret
= midiInGetDevCapsA(uDeviceID
, &micA
, uSize
);
2644 if (ret
== MMSYSERR_NOERROR
) {
2645 lpCaps
->wMid
= micA
.wMid
;
2646 lpCaps
->wPid
= micA
.wPid
;
2647 lpCaps
->vDriverVersion
= micA
.vDriverVersion
;
2648 MultiByteToWideChar( CP_ACP
, 0, micA
.szPname
, -1, lpCaps
->szPname
,
2649 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
2650 lpCaps
->dwSupport
= micA
.dwSupport
;
2655 /**************************************************************************
2656 * midiInGetDevCapsA [WINMM.@]
2658 UINT WINAPI
midiInGetDevCapsA(UINT uDeviceID
, LPMIDIINCAPSA lpCaps
, UINT uSize
)
2662 TRACE("(%d, %p, %d);\n", uDeviceID
, lpCaps
, uSize
);
2664 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_MIDIIN
, TRUE
)) == NULL
)
2665 return MMSYSERR_INVALHANDLE
;
2667 return MMDRV_Message(wmld
, MIDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
2670 /**************************************************************************
2671 * midiInGetDevCaps [MMSYSTEM.302]
2673 UINT16 WINAPI
midiInGetDevCaps16(UINT16 uDeviceID
, LPMIDIINCAPS16 lpCaps
,
2677 UINT ret
= midiInGetDevCapsA(uDeviceID
, &micA
, uSize
);
2679 if (ret
== MMSYSERR_NOERROR
) {
2680 lpCaps
->wMid
= micA
.wMid
;
2681 lpCaps
->wPid
= micA
.wPid
;
2682 lpCaps
->vDriverVersion
= micA
.vDriverVersion
;
2683 strcpy(lpCaps
->szPname
, micA
.szPname
);
2684 lpCaps
->dwSupport
= micA
.dwSupport
;
2690 /**************************************************************************
2691 * midiInGetErrorTextW [WINMM.@]
2693 UINT WINAPI
midiInGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
2695 LPSTR xstr
= HeapAlloc(GetProcessHeap(), 0, uSize
);
2696 UINT ret
= MIDI_GetErrorText(uError
, xstr
, uSize
);
2698 MultiByteToWideChar( CP_ACP
, 0, xstr
, -1, lpText
, uSize
);
2699 HeapFree(GetProcessHeap(), 0, xstr
);
2703 /**************************************************************************
2704 * midiInGetErrorTextA [WINMM.@]
2706 UINT WINAPI
midiInGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
2708 return MIDI_GetErrorText(uError
, lpText
, uSize
);
2711 /**************************************************************************
2712 * midiInGetErrorText [MMSYSTEM.303]
2714 UINT16 WINAPI
midiInGetErrorText16(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
2716 return MIDI_GetErrorText(uError
, lpText
, uSize
);
2719 static UINT
MMSYSTEM_midiInOpen(HMIDIIN
* lphMidiIn
, UINT uDeviceID
, DWORD dwCallback
,
2720 DWORD dwInstance
, DWORD dwFlags
, BOOL bFrom32
)
2726 TRACE("(%p, %d, %08lX, %08lX, %08lX);\n",
2727 lphMidiIn
, uDeviceID
, dwCallback
, dwInstance
, dwFlags
);
2729 if (lphMidiIn
!= NULL
) *lphMidiIn
= 0;
2731 lpwm
= (LPWINE_MIDI
)MMDRV_Alloc(sizeof(WINE_MIDI
), MMDRV_MIDIIN
, &hMidiIn
,
2732 &dwFlags
, &dwCallback
, &dwInstance
, bFrom32
);
2735 return MMSYSERR_NOMEM
;
2737 lpwm
->mod
.hMidi
= hMidiIn
;
2738 lpwm
->mod
.dwCallback
= dwCallback
;
2739 lpwm
->mod
.dwInstance
= dwInstance
;
2741 lpwm
->mld
.uDeviceID
= uDeviceID
;
2742 dwRet
= MMDRV_Open(&lpwm
->mld
, MIDM_OPEN
, (DWORD
)&lpwm
->mod
, dwFlags
);
2744 if (dwRet
!= MMSYSERR_NOERROR
) {
2745 MMDRV_Free(hMidiIn
, &lpwm
->mld
);
2748 if (lphMidiIn
!= NULL
) *lphMidiIn
= hMidiIn
;
2749 TRACE("=> %ld hMidi=%04x\n", dwRet
, hMidiIn
);
2754 /**************************************************************************
2755 * midiInOpen [WINMM.@]
2757 UINT WINAPI
midiInOpen(HMIDIIN
* lphMidiIn
, UINT uDeviceID
,
2758 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
2760 return MMSYSTEM_midiInOpen(lphMidiIn
, uDeviceID
, dwCallback
,
2761 dwInstance
, dwFlags
, TRUE
);
2764 /**************************************************************************
2765 * midiInOpen [MMSYSTEM.304]
2767 UINT16 WINAPI
midiInOpen16(HMIDIIN16
* lphMidiIn
, UINT16 uDeviceID
,
2768 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
2773 ret
= MMSYSTEM_midiInOpen(&xhmid
, uDeviceID
, dwCallback
, dwInstance
,
2776 if (lphMidiIn
) *lphMidiIn
= xhmid
;
2780 /**************************************************************************
2781 * midiInClose [WINMM.@]
2783 UINT WINAPI
midiInClose(HMIDIIN hMidiIn
)
2788 TRACE("(%04X)\n", hMidiIn
);
2790 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2791 return MMSYSERR_INVALHANDLE
;
2793 dwRet
= MMDRV_Close(wmld
, MIDM_CLOSE
);
2794 MMDRV_Free(hMidiIn
, wmld
);
2798 /**************************************************************************
2799 * midiInClose [MMSYSTEM.305]
2801 UINT16 WINAPI
midiInClose16(HMIDIIN16 hMidiIn
)
2803 return midiInClose(hMidiIn
);
2806 /**************************************************************************
2807 * midiInPrepareHeader [WINMM.@]
2809 UINT WINAPI
midiInPrepareHeader(HMIDIIN hMidiIn
,
2810 MIDIHDR
* lpMidiInHdr
, UINT uSize
)
2814 TRACE("(%04X, %p, %d)\n", hMidiIn
, lpMidiInHdr
, uSize
);
2816 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2817 return MMSYSERR_INVALHANDLE
;
2819 return MMDRV_Message(wmld
, MIDM_PREPARE
, (DWORD
)lpMidiInHdr
, uSize
, TRUE
);
2822 /**************************************************************************
2823 * midiInPrepareHeader [MMSYSTEM.306]
2825 UINT16 WINAPI
midiInPrepareHeader16(HMIDIIN16 hMidiIn
, /* [in] */
2826 SEGPTR lpsegMidiInHdr
, /* [???] */
2827 UINT16 uSize
) /* [in] */
2831 TRACE("(%04X, %08lx, %d)\n", hMidiIn
, lpsegMidiInHdr
, uSize
);
2833 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2834 return MMSYSERR_INVALHANDLE
;
2836 return MMDRV_Message(wmld
, MIDM_PREPARE
, (DWORD
)lpsegMidiInHdr
, uSize
, FALSE
);
2839 /**************************************************************************
2840 * midiInUnprepareHeader [WINMM.@]
2842 UINT WINAPI
midiInUnprepareHeader(HMIDIIN hMidiIn
,
2843 MIDIHDR
* lpMidiInHdr
, UINT uSize
)
2847 TRACE("(%04X, %p, %d)\n", hMidiIn
, lpMidiInHdr
, uSize
);
2849 if (!(lpMidiInHdr
->dwFlags
& MHDR_PREPARED
)) {
2850 return MMSYSERR_NOERROR
;
2853 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2854 return MMSYSERR_INVALHANDLE
;
2856 return MMDRV_Message(wmld
, MIDM_UNPREPARE
, (DWORD
)lpMidiInHdr
, uSize
, TRUE
);
2859 /**************************************************************************
2860 * midiInUnprepareHeader [MMSYSTEM.307]
2862 UINT16 WINAPI
midiInUnprepareHeader16(HMIDIIN16 hMidiIn
, /* [in] */
2863 SEGPTR lpsegMidiInHdr
, /* [???] */
2864 UINT16 uSize
) /* [in] */
2867 LPMIDIHDR16 lpMidiInHdr
= MapSL(lpsegMidiInHdr
);
2869 TRACE("(%04X, %08lx, %d)\n", hMidiIn
, lpsegMidiInHdr
, uSize
);
2871 if (!(lpMidiInHdr
->dwFlags
& MHDR_PREPARED
)) {
2872 return MMSYSERR_NOERROR
;
2875 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2876 return MMSYSERR_INVALHANDLE
;
2878 return MMDRV_Message(wmld
, MIDM_UNPREPARE
, (DWORD
)lpsegMidiInHdr
, uSize
, FALSE
);
2881 /**************************************************************************
2882 * midiInAddBuffer [WINMM.@]
2884 UINT WINAPI
midiInAddBuffer(HMIDIIN hMidiIn
,
2885 MIDIHDR
* lpMidiInHdr
, UINT uSize
)
2889 TRACE("(%04X, %p, %d)\n", hMidiIn
, lpMidiInHdr
, uSize
);
2891 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2892 return MMSYSERR_INVALHANDLE
;
2894 return MMDRV_Message(wmld
, MIDM_ADDBUFFER
, (DWORD
)lpMidiInHdr
, uSize
, TRUE
);
2897 /**************************************************************************
2898 * midiInAddBuffer [MMSYSTEM.308]
2900 UINT16 WINAPI
midiInAddBuffer16(HMIDIIN16 hMidiIn
, /* [in] */
2901 MIDIHDR16
* lpsegMidiInHdr
, /* [???] NOTE: SEGPTR */
2902 UINT16 uSize
) /* [in] */
2906 TRACE("(%04X, %p, %d)\n", hMidiIn
, lpsegMidiInHdr
, uSize
);
2908 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2909 return MMSYSERR_INVALHANDLE
;
2911 return MMDRV_Message(wmld
, MIDM_ADDBUFFER
, (DWORD
)lpsegMidiInHdr
, uSize
, FALSE
);
2914 /**************************************************************************
2915 * midiInStart [WINMM.@]
2917 UINT WINAPI
midiInStart(HMIDIIN hMidiIn
)
2921 TRACE("(%04X)\n", hMidiIn
);
2923 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2924 return MMSYSERR_INVALHANDLE
;
2926 return MMDRV_Message(wmld
, MIDM_START
, 0L, 0L, TRUE
);
2929 /**************************************************************************
2930 * midiInStart [MMSYSTEM.309]
2932 UINT16 WINAPI
midiInStart16(HMIDIIN16 hMidiIn
)
2934 return midiInStart(hMidiIn
);
2937 /**************************************************************************
2938 * midiInStop [WINMM.@]
2940 UINT WINAPI
midiInStop(HMIDIIN hMidiIn
)
2944 TRACE("(%04X)\n", hMidiIn
);
2946 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2947 return MMSYSERR_INVALHANDLE
;
2949 return MMDRV_Message(wmld
, MIDM_STOP
, 0L, 0L, TRUE
);
2952 /**************************************************************************
2953 * midiInStop [MMSYSTEM.310]
2955 UINT16 WINAPI
midiInStop16(HMIDIIN16 hMidiIn
)
2957 return midiInStop(hMidiIn
);
2960 /**************************************************************************
2961 * midiInReset [WINMM.@]
2963 UINT WINAPI
midiInReset(HMIDIIN hMidiIn
)
2967 TRACE("(%04X)\n", hMidiIn
);
2969 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2970 return MMSYSERR_INVALHANDLE
;
2972 return MMDRV_Message(wmld
, MIDM_RESET
, 0L, 0L, TRUE
);
2975 /**************************************************************************
2976 * midiInReset [MMSYSTEM.311]
2978 UINT16 WINAPI
midiInReset16(HMIDIIN16 hMidiIn
)
2980 return midiInReset(hMidiIn
);
2983 /**************************************************************************
2984 * midiInGetID [WINMM.@]
2986 UINT WINAPI
midiInGetID(HMIDIIN hMidiIn
, UINT
* lpuDeviceID
)
2990 TRACE("(%04X, %p)\n", hMidiIn
, lpuDeviceID
);
2992 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
2994 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, TRUE
)) == NULL
)
2995 return MMSYSERR_INVALHANDLE
;
2997 *lpuDeviceID
= wmld
->uDeviceID
;
2999 return MMSYSERR_NOERROR
;
3002 /**************************************************************************
3003 * midiInGetID [MMSYSTEM.312]
3005 UINT16 WINAPI
midiInGetID16(HMIDIIN16 hMidiIn
, UINT16
* lpuDeviceID
)
3009 TRACE("(%04X, %p)\n", hMidiIn
, lpuDeviceID
);
3011 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
3013 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, TRUE
)) == NULL
)
3014 return MMSYSERR_INVALHANDLE
;
3016 *lpuDeviceID
= wmld
->uDeviceID
;
3018 return MMSYSERR_NOERROR
;
3021 /**************************************************************************
3022 * midiInMessage [WINMM.@]
3024 DWORD WINAPI
midiInMessage(HMIDIIN hMidiIn
, UINT uMessage
,
3025 DWORD dwParam1
, DWORD dwParam2
)
3029 TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiIn
, uMessage
, dwParam1
, dwParam2
);
3031 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
3032 return MMSYSERR_INVALHANDLE
;
3037 FIXME("can't handle OPEN or CLOSE message!\n");
3038 return MMSYSERR_NOTSUPPORTED
;
3040 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
3043 /**************************************************************************
3044 * midiInMessage [MMSYSTEM.313]
3046 DWORD WINAPI
midiInMessage16(HMIDIIN16 hMidiIn
, UINT16 uMessage
,
3047 DWORD dwParam1
, DWORD dwParam2
)
3051 TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiIn
, uMessage
, dwParam1
, dwParam2
);
3056 FIXME("can't handle OPEN or CLOSE message!\n");
3057 return MMSYSERR_NOTSUPPORTED
;
3059 case MIDM_GETDEVCAPS
:
3060 return midiInGetDevCaps16(hMidiIn
, MapSL(dwParam1
), dwParam2
);
3062 return midiInPrepareHeader16(hMidiIn
, dwParam1
, dwParam2
);
3063 case MIDM_UNPREPARE
:
3064 return midiInUnprepareHeader16(hMidiIn
, dwParam1
, dwParam2
);
3065 case MIDM_ADDBUFFER
:
3066 return midiInAddBuffer16(hMidiIn
, MapSL(dwParam1
), dwParam2
);
3069 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
3070 return MMSYSERR_INVALHANDLE
;
3072 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, FALSE
);
3075 typedef struct WINE_MIDIStream
{
3086 LPMIDIHDR lpMidiHdr
;
3089 #define WINE_MSM_HEADER (WM_USER+0)
3090 #define WINE_MSM_STOP (WM_USER+1)
3092 /**************************************************************************
3093 * MMSYSTEM_GetMidiStream [internal]
3095 static BOOL
MMSYSTEM_GetMidiStream(HMIDISTRM hMidiStrm
, WINE_MIDIStream
** lpMidiStrm
, WINE_MIDI
** lplpwm
)
3097 WINE_MIDI
* lpwm
= (LPWINE_MIDI
)MMDRV_Get(hMidiStrm
, MMDRV_MIDIOUT
, FALSE
);
3106 *lpMidiStrm
= (WINE_MIDIStream
*)lpwm
->mod
.rgIds
.dwStreamID
;
3108 return *lpMidiStrm
!= NULL
;
3111 /**************************************************************************
3112 * MMSYSTEM_MidiStream_Convert [internal]
3114 static DWORD
MMSYSTEM_MidiStream_Convert(WINE_MIDIStream
* lpMidiStrm
, DWORD pulse
)
3118 if (lpMidiStrm
->dwTimeDiv
== 0) {
3119 FIXME("Shouldn't happen. lpMidiStrm->dwTimeDiv = 0\n");
3120 } else if (lpMidiStrm
->dwTimeDiv
> 0x8000) { /* SMPTE, unchecked FIXME? */
3121 int nf
= -(char)HIBYTE(lpMidiStrm
->dwTimeDiv
); /* number of frames */
3122 int nsf
= LOBYTE(lpMidiStrm
->dwTimeDiv
); /* number of sub-frames */
3123 ret
= (pulse
* 1000) / (nf
* nsf
);
3125 ret
= (DWORD
)((double)pulse
* ((double)lpMidiStrm
->dwTempo
/ 1000) /
3126 (double)lpMidiStrm
->dwTimeDiv
);
3132 /**************************************************************************
3133 * MMSYSTEM_MidiStream_MessageHandler [internal]
3135 static BOOL
MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream
* lpMidiStrm
, LPWINE_MIDI lpwm
, LPMSG msg
)
3137 LPMIDIHDR lpMidiHdr
;
3141 switch (msg
->message
) {
3143 SetEvent(lpMidiStrm
->hEvent
);
3147 /* this is not quite what MS doc says... */
3148 midiOutReset(lpMidiStrm
->hDevice
);
3149 /* empty list of already submitted buffers */
3150 for (lpMidiHdr
= lpMidiStrm
->lpMidiHdr
; lpMidiHdr
; lpMidiHdr
= (LPMIDIHDR
)lpMidiHdr
->lpNext
) {
3151 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
3152 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
3154 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
, lpMidiStrm
->hDevice
,
3155 MM_MOM_DONE
, lpwm
->mod
.dwInstance
, (DWORD
)lpMidiHdr
, 0L);
3157 lpMidiStrm
->lpMidiHdr
= 0;
3158 SetEvent(lpMidiStrm
->hEvent
);
3160 case WINE_MSM_HEADER
:
3161 /* sets initial tick count for first MIDIHDR */
3162 if (!lpMidiStrm
->dwStartTicks
)
3163 lpMidiStrm
->dwStartTicks
= GetTickCount();
3165 /* FIXME(EPP): "I don't understand the content of the first MIDIHDR sent
3166 * by native mcimidi, it doesn't look like a correct one".
3167 * this trick allows to throw it away... but I don't like it.
3168 * It looks like part of the file I'm trying to play and definitively looks
3169 * like raw midi content
3170 * I'd really like to understand why native mcimidi sends it. Perhaps a bad
3171 * synchronization issue where native mcimidi is still processing raw MIDI
3172 * content before generating MIDIEVENTs ?
3174 * 4c 04 89 3b 00 81 7c 99 3b 43 00 99 23 5e 04 89 L..;..|.;C..#^..
3175 * 3b 00 00 89 23 00 7c 99 3b 45 00 99 28 62 04 89 ;...#.|.;E..(b..
3176 * 3b 00 00 89 28 00 81 7c 99 3b 4e 00 99 23 5e 04 ;...(..|.;N..#^.
3177 * 89 3b 00 00 89 23 00 7c 99 3b 45 00 99 23 78 04 .;...#.|.;E..#x.
3178 * 89 3b 00 00 89 23 00 81 7c 99 3b 48 00 99 23 5e .;...#..|.;H..#^
3179 * 04 89 3b 00 00 89 23 00 7c 99 3b 4e 00 99 28 62 ..;...#.|.;N..(b
3180 * 04 89 3b 00 00 89 28 00 81 7c 99 39 4c 00 99 23 ..;...(..|.9L..#
3181 * 5e 04 89 39 00 00 89 23 00 82 7c 99 3b 4c 00 99 ^..9...#..|.;L..
3182 * 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b 48 00 99 #^..;...#.|.;H..
3183 * 28 62 04 89 3b 00 00 89 28 00 81 7c 99 3b 3f 04 (b..;...(..|.;?.
3184 * 89 3b 00 1c 99 23 5e 04 89 23 00 5c 99 3b 45 00 .;...#^..#.\.;E.
3185 * 99 23 78 04 89 3b 00 00 89 23 00 81 7c 99 3b 46 .#x..;...#..|.;F
3186 * 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b 48 ..#^..;...#.|.;H
3187 * 00 99 28 62 04 89 3b 00 00 89 28 00 81 7c 99 3b ..(b..;...(..|.;
3188 * 46 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b F..#^..;...#.|.;
3189 * 48 00 99 23 78 04 89 3b 00 00 89 23 00 81 7c 99 H..#x..;...#..|.
3190 * 3b 4c 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 ;L..#^..;...#.|.
3192 lpMidiHdr
= (LPMIDIHDR
)msg
->lParam
;
3193 lpData
= lpMidiHdr
->lpData
;
3194 TRACE("Adding %s lpMidiHdr=%p [lpData=0x%08lx dwBufferLength=%lu/%lu dwFlags=0x%08lx size=%u]\n",
3195 (lpMidiHdr
->dwFlags
& MHDR_ISSTRM
) ? "stream" : "regular", lpMidiHdr
,
3196 (DWORD
)lpMidiHdr
, lpMidiHdr
->dwBufferLength
, lpMidiHdr
->dwBytesRecorded
,
3197 lpMidiHdr
->dwFlags
, msg
->wParam
);
3199 /* dumps content of lpMidiHdr->lpData
3200 * FIXME: there should be a debug routine somewhere that already does this
3201 * I hate spreading this type of shit all around the code
3203 for (dwToGo
= 0; dwToGo
< lpMidiHdr
->dwBufferLength
; dwToGo
+= 16) {
3207 for (i
= 0; i
< min(16, lpMidiHdr
->dwBufferLength
- dwToGo
); i
++)
3208 printf("%02x ", lpData
[dwToGo
+ i
]);
3211 for (i
= 0; i
< min(16, lpMidiHdr
->dwBufferLength
- dwToGo
); i
++) {
3212 ch
= lpData
[dwToGo
+ i
];
3213 printf("%c", (ch
>= 0x20 && ch
<= 0x7F) ? ch
: '.');
3218 if (((LPMIDIEVENT
)lpData
)->dwStreamID
!= 0 &&
3219 ((LPMIDIEVENT
)lpData
)->dwStreamID
!= 0xFFFFFFFF &&
3220 ((LPMIDIEVENT
)lpData
)->dwStreamID
!= (DWORD
)lpMidiStrm
) {
3221 FIXME("Dropping bad %s lpMidiHdr (streamID=%08lx)\n",
3222 (lpMidiHdr
->dwFlags
& MHDR_ISSTRM
) ? "stream" : "regular",
3223 ((LPMIDIEVENT
)lpData
)->dwStreamID
);
3224 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
3225 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
3227 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
, lpMidiStrm
->hDevice
,
3228 MM_MOM_DONE
, lpwm
->mod
.dwInstance
, (DWORD
)lpMidiHdr
, 0L);
3232 for (lpmh
= &lpMidiStrm
->lpMidiHdr
; *lpmh
; lpmh
= (LPMIDIHDR
*)&((*lpmh
)->lpNext
));
3234 lpMidiHdr
= (LPMIDIHDR
)msg
->lParam
;
3235 lpMidiHdr
->lpNext
= 0;
3236 lpMidiHdr
->dwFlags
|= MHDR_INQUEUE
;
3237 lpMidiHdr
->dwFlags
&= MHDR_DONE
;
3238 lpMidiHdr
->dwOffset
= 0;
3242 FIXME("Unknown message %d\n", msg
->message
);
3248 /**************************************************************************
3249 * MMSYSTEM_MidiStream_Player [internal]
3251 static DWORD CALLBACK
MMSYSTEM_MidiStream_Player(LPVOID pmt
)
3253 WINE_MIDIStream
* lpMidiStrm
= pmt
;
3258 LPMIDIHDR lpMidiHdr
;
3262 TRACE("(%p)!\n", lpMidiStrm
);
3265 (lpwm
= (LPWINE_MIDI
)MMDRV_Get(lpMidiStrm
->hDevice
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
3268 /* force thread's queue creation */
3269 /* Used to be InitThreadInput16(0, 5); */
3270 /* but following works also with hack in midiStreamOpen */
3271 PeekMessageA(&msg
, 0, 0, 0, 0);
3273 /* FIXME: this next line must be called before midiStreamOut or midiStreamRestart are called */
3274 SetEvent(lpMidiStrm
->hEvent
);
3275 TRACE("Ready to go 1\n");
3276 /* thread is started in paused mode */
3277 SuspendThread(lpMidiStrm
->hThread
);
3278 TRACE("Ready to go 2\n");
3280 lpMidiStrm
->dwStartTicks
= 0;
3281 lpMidiStrm
->dwPulses
= 0;
3283 lpMidiStrm
->lpMidiHdr
= 0;
3286 lpMidiHdr
= lpMidiStrm
->lpMidiHdr
;
3288 /* for first message, block until one arrives, then process all that are available */
3289 GetMessageA(&msg
, 0, 0, 0);
3291 if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm
, lpwm
, &msg
))
3293 } while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
));
3299 lpData
= lpMidiHdr
->lpData
;
3301 me
= (LPMIDIEVENT
)(lpData
+ lpMidiHdr
->dwOffset
);
3303 /* do we have to wait ? */
3304 if (me
->dwDeltaTime
) {
3305 lpMidiStrm
->dwPositionMS
+= MMSYSTEM_MidiStream_Convert(lpMidiStrm
, me
->dwDeltaTime
);
3306 lpMidiStrm
->dwPulses
+= me
->dwDeltaTime
;
3308 dwToGo
= lpMidiStrm
->dwStartTicks
+ lpMidiStrm
->dwPositionMS
;
3310 TRACE("%ld/%ld/%ld\n", dwToGo
, GetTickCount(), me
->dwDeltaTime
);
3311 while ((dwCurrTC
= GetTickCount()) < dwToGo
) {
3312 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, dwToGo
- dwCurrTC
, QS_ALLINPUT
) == WAIT_OBJECT_0
) {
3313 /* got a message, handle it */
3314 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) {
3315 if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm
, lpwm
, &msg
))
3320 /* timeout, so me->dwDeltaTime is elapsed, can break the while loop */
3325 switch (MEVT_EVENTTYPE(me
->dwEvent
& ~MEVT_F_CALLBACK
)) {
3327 FIXME("NIY: MEVT_COMMENT\n");
3328 /* do nothing, skip bytes */
3331 FIXME("NIY: MEVT_LONGMSG, aka sending Sysex event\n");
3336 midiOutShortMsg(lpMidiStrm
->hDevice
, MEVT_EVENTPARM(me
->dwEvent
));
3339 lpMidiStrm
->dwTempo
= MEVT_EVENTPARM(me
->dwEvent
);
3344 FIXME("Unknown MEVT (0x%02x)\n", MEVT_EVENTTYPE(me
->dwEvent
& ~MEVT_F_CALLBACK
));
3347 if (me
->dwEvent
& MEVT_F_CALLBACK
) {
3348 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
, lpMidiStrm
->hDevice
,
3349 MM_MOM_POSITIONCB
, lpwm
->mod
.dwInstance
, (LPARAM
)lpMidiHdr
, 0L);
3351 lpMidiHdr
->dwOffset
+= sizeof(MIDIEVENT
) - sizeof(me
->dwParms
);
3352 if (me
->dwEvent
& MEVT_F_LONG
)
3353 lpMidiHdr
->dwOffset
+= (MEVT_EVENTPARM(me
->dwEvent
) + 3) & ~3;
3354 if (lpMidiHdr
->dwOffset
>= lpMidiHdr
->dwBufferLength
) {
3355 /* done with this header */
3356 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
3357 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
3359 lpMidiStrm
->lpMidiHdr
= (LPMIDIHDR
)lpMidiHdr
->lpNext
;
3360 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
, lpMidiStrm
->hDevice
,
3361 MM_MOM_DONE
, lpwm
->mod
.dwInstance
, (DWORD
)lpMidiHdr
, 0L);
3366 TRACE("End of thread\n");
3368 return 0; /* for removing the warning, never executed */
3371 /**************************************************************************
3372 * MMSYSTEM_MidiStream_PostMessage [internal]
3374 static BOOL
MMSYSTEM_MidiStream_PostMessage(WINE_MIDIStream
* lpMidiStrm
, WORD msg
, DWORD pmt1
, DWORD pmt2
)
3376 if (PostThreadMessageA(lpMidiStrm
->dwThreadID
, msg
, pmt1
, pmt2
)) {
3379 ReleaseThunkLock(&count
);
3380 WaitForSingleObject(lpMidiStrm
->hEvent
, INFINITE
);
3381 RestoreThunkLock(count
);
3383 WARN("bad PostThreadMessageA\n");
3389 /**************************************************************************
3390 * midiStreamClose [WINMM.@]
3392 MMRESULT WINAPI
midiStreamClose(HMIDISTRM hMidiStrm
)
3394 WINE_MIDIStream
* lpMidiStrm
;
3396 TRACE("(%08x)!\n", hMidiStrm
);
3398 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
))
3399 return MMSYSERR_INVALHANDLE
;
3401 midiStreamStop(hMidiStrm
);
3402 MMSYSTEM_MidiStream_PostMessage(lpMidiStrm
, WM_QUIT
, 0, 0);
3403 HeapFree(GetProcessHeap(), 0, lpMidiStrm
);
3404 CloseHandle(lpMidiStrm
->hEvent
);
3406 return midiOutClose(hMidiStrm
);
3409 /**************************************************************************
3410 * MMSYSTEM_MidiStream_Open [internal]
3412 static MMRESULT WINAPI
MMSYSTEM_MidiStream_Open(HMIDISTRM
* lphMidiStrm
, LPUINT lpuDeviceID
,
3413 DWORD cMidi
, DWORD dwCallback
,
3414 DWORD dwInstance
, DWORD fdwOpen
, BOOL bFrom32
)
3416 WINE_MIDIStream
* lpMidiStrm
;
3418 MIDIOPENSTRMID mosm
;
3422 TRACE("(%p, %p, %ld, 0x%08lx, 0x%08lx, 0x%08lx)!\n",
3423 lphMidiStrm
, lpuDeviceID
, cMidi
, dwCallback
, dwInstance
, fdwOpen
);
3425 if (cMidi
!= 1 || lphMidiStrm
== NULL
|| lpuDeviceID
== NULL
)
3426 return MMSYSERR_INVALPARAM
;
3428 lpMidiStrm
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_MIDIStream
));
3430 return MMSYSERR_NOMEM
;
3432 lpMidiStrm
->dwTempo
= 500000;
3433 lpMidiStrm
->dwTimeDiv
= 480; /* 480 is 120 quater notes per minute *//* FIXME ??*/
3434 lpMidiStrm
->dwPositionMS
= 0;
3436 mosm
.dwStreamID
= (DWORD
)lpMidiStrm
;
3437 /* FIXME: the correct value is not allocated yet for MAPPER */
3438 mosm
.wDeviceID
= *lpuDeviceID
;
3439 lpwm
= MIDI_OutAlloc(&hMidiOut
, &dwCallback
, &dwInstance
, &fdwOpen
, 1, &mosm
, bFrom32
);
3440 lpMidiStrm
->hDevice
= hMidiOut
;
3442 *lphMidiStrm
= hMidiOut
;
3444 /* FIXME: is lpuDevice initialized upon entering midiStreamOpen ? */
3445 FIXME("*lpuDeviceID=%x\n", *lpuDeviceID
);
3446 lpwm
->mld
.uDeviceID
= *lpuDeviceID
= 0;
3448 ret
= MMDRV_Open(&lpwm
->mld
, MODM_OPEN
, (DWORD
)&lpwm
->mod
, fdwOpen
);
3449 lpMidiStrm
->hEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3450 lpMidiStrm
->wFlags
= HIWORD(fdwOpen
);
3452 lpMidiStrm
->hThread
= CreateThread(NULL
, 0, MMSYSTEM_MidiStream_Player
,
3453 lpMidiStrm
, 0, &(lpMidiStrm
->dwThreadID
));
3455 if (!lpMidiStrm
->hThread
) {
3456 midiStreamClose((HMIDISTRM
)hMidiOut
);
3457 return MMSYSERR_NOMEM
;
3460 /* wait for thread to have started, and for its queue to be created */
3464 /* (Release|Restore)ThunkLock() is needed when this method is called from 16 bit code,
3465 * (meaning the Win16Lock is set), so that it's released and the 32 bit thread running
3466 * MMSYSTEM_MidiStreamPlayer can acquire Win16Lock to create its queue.
3468 ReleaseThunkLock(&count
);
3469 WaitForSingleObject(lpMidiStrm
->hEvent
, INFINITE
);
3470 RestoreThunkLock(count
);
3473 TRACE("=> (%u/%d) hMidi=0x%04x ret=%d lpMidiStrm=%p\n",
3474 *lpuDeviceID
, lpwm
->mld
.uDeviceID
, *lphMidiStrm
, ret
, lpMidiStrm
);
3478 /**************************************************************************
3479 * midiStreamOpen [WINMM.@]
3481 MMRESULT WINAPI
midiStreamOpen(HMIDISTRM
* lphMidiStrm
, LPUINT lpuDeviceID
,
3482 DWORD cMidi
, DWORD dwCallback
,
3483 DWORD dwInstance
, DWORD fdwOpen
)
3485 return MMSYSTEM_MidiStream_Open(lphMidiStrm
, lpuDeviceID
, cMidi
, dwCallback
,
3486 dwInstance
, fdwOpen
, TRUE
);
3489 /**************************************************************************
3490 * midiStreamOut [WINMM.@]
3492 MMRESULT WINAPI
midiStreamOut(HMIDISTRM hMidiStrm
, LPMIDIHDR lpMidiHdr
,
3495 WINE_MIDIStream
* lpMidiStrm
;
3496 DWORD ret
= MMSYSERR_NOERROR
;
3498 TRACE("(%08x, %p, %u)!\n", hMidiStrm
, lpMidiHdr
, cbMidiHdr
);
3500 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3501 ret
= MMSYSERR_INVALHANDLE
;
3502 } else if (!lpMidiHdr
) {
3503 ret
= MMSYSERR_INVALPARAM
;
3505 if (!PostThreadMessageA(lpMidiStrm
->dwThreadID
,
3506 WINE_MSM_HEADER
, cbMidiHdr
,
3507 (DWORD
)lpMidiHdr
)) {
3508 WARN("bad PostThreadMessageA\n");
3509 ret
= MMSYSERR_ERROR
;
3515 /**************************************************************************
3516 * midiStreamPause [WINMM.@]
3518 MMRESULT WINAPI
midiStreamPause(HMIDISTRM hMidiStrm
)
3520 WINE_MIDIStream
* lpMidiStrm
;
3521 DWORD ret
= MMSYSERR_NOERROR
;
3523 TRACE("(%08x)!\n", hMidiStrm
);
3525 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3526 ret
= MMSYSERR_INVALHANDLE
;
3528 if (SuspendThread(lpMidiStrm
->hThread
) == 0xFFFFFFFF) {
3529 WARN("bad Suspend (%ld)\n", GetLastError());
3530 ret
= MMSYSERR_ERROR
;
3536 /**************************************************************************
3537 * midiStreamPosition [WINMM.@]
3539 MMRESULT WINAPI
midiStreamPosition(HMIDISTRM hMidiStrm
, LPMMTIME lpMMT
, UINT cbmmt
)
3541 WINE_MIDIStream
* lpMidiStrm
;
3542 DWORD ret
= MMSYSERR_NOERROR
;
3544 TRACE("(%08x, %p, %u)!\n", hMidiStrm
, lpMMT
, cbmmt
);
3546 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3547 ret
= MMSYSERR_INVALHANDLE
;
3548 } else if (lpMMT
== NULL
|| cbmmt
!= sizeof(MMTIME
)) {
3549 ret
= MMSYSERR_INVALPARAM
;
3551 switch (lpMMT
->wType
) {
3553 lpMMT
->u
.ms
= lpMidiStrm
->dwPositionMS
;
3554 TRACE("=> %ld ms\n", lpMMT
->u
.ms
);
3557 lpMMT
->u
.ticks
= lpMidiStrm
->dwPulses
;
3558 TRACE("=> %ld ticks\n", lpMMT
->u
.ticks
);
3561 WARN("Unsupported time type %d\n", lpMMT
->wType
);
3562 lpMMT
->wType
= TIME_MS
;
3563 ret
= MMSYSERR_INVALPARAM
;
3570 /**************************************************************************
3571 * midiStreamProperty [WINMM.@]
3573 MMRESULT WINAPI
midiStreamProperty(HMIDISTRM hMidiStrm
, LPBYTE lpPropData
, DWORD dwProperty
)
3575 WINE_MIDIStream
* lpMidiStrm
;
3576 MMRESULT ret
= MMSYSERR_NOERROR
;
3578 TRACE("(%08x, %p, %lx)\n", hMidiStrm
, lpPropData
, dwProperty
);
3580 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3581 ret
= MMSYSERR_INVALHANDLE
;
3582 } else if ((dwProperty
& (MIDIPROP_GET
|MIDIPROP_SET
)) == 0) {
3583 ret
= MMSYSERR_INVALPARAM
;
3584 } else if (dwProperty
& MIDIPROP_TEMPO
) {
3585 MIDIPROPTEMPO
* mpt
= (MIDIPROPTEMPO
*)lpPropData
;
3587 if (sizeof(MIDIPROPTEMPO
) != mpt
->cbStruct
) {
3588 ret
= MMSYSERR_INVALPARAM
;
3589 } else if (dwProperty
& MIDIPROP_SET
) {
3590 lpMidiStrm
->dwTempo
= mpt
->dwTempo
;
3591 TRACE("Setting tempo to %ld\n", mpt
->dwTempo
);
3592 } else if (dwProperty
& MIDIPROP_GET
) {
3593 mpt
->dwTempo
= lpMidiStrm
->dwTempo
;
3594 TRACE("Getting tempo <= %ld\n", mpt
->dwTempo
);
3596 } else if (dwProperty
& MIDIPROP_TIMEDIV
) {
3597 MIDIPROPTIMEDIV
* mptd
= (MIDIPROPTIMEDIV
*)lpPropData
;
3599 if (sizeof(MIDIPROPTIMEDIV
) != mptd
->cbStruct
) {
3600 ret
= MMSYSERR_INVALPARAM
;
3601 } else if (dwProperty
& MIDIPROP_SET
) {
3602 lpMidiStrm
->dwTimeDiv
= mptd
->dwTimeDiv
;
3603 TRACE("Setting time div to %ld\n", mptd
->dwTimeDiv
);
3604 } else if (dwProperty
& MIDIPROP_GET
) {
3605 mptd
->dwTimeDiv
= lpMidiStrm
->dwTimeDiv
;
3606 TRACE("Getting time div <= %ld\n", mptd
->dwTimeDiv
);
3609 ret
= MMSYSERR_INVALPARAM
;
3615 /**************************************************************************
3616 * midiStreamRestart [WINMM.@]
3618 MMRESULT WINAPI
midiStreamRestart(HMIDISTRM hMidiStrm
)
3620 WINE_MIDIStream
* lpMidiStrm
;
3621 MMRESULT ret
= MMSYSERR_NOERROR
;
3623 TRACE("(%08x)!\n", hMidiStrm
);
3625 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3626 ret
= MMSYSERR_INVALHANDLE
;
3630 /* since we increase the thread suspend count on each midiStreamPause
3631 * there may be a need for several midiStreamResume
3634 ret
= ResumeThread(lpMidiStrm
->hThread
);
3635 } while (ret
!= 0xFFFFFFFF && ret
!= 0);
3636 if (ret
== 0xFFFFFFFF) {
3637 WARN("bad Resume (%ld)\n", GetLastError());
3638 ret
= MMSYSERR_ERROR
;
3640 lpMidiStrm
->dwStartTicks
= GetTickCount() - lpMidiStrm
->dwPositionMS
;
3646 /**************************************************************************
3647 * midiStreamStop [WINMM.@]
3649 MMRESULT WINAPI
midiStreamStop(HMIDISTRM hMidiStrm
)
3651 WINE_MIDIStream
* lpMidiStrm
;
3652 MMRESULT ret
= MMSYSERR_NOERROR
;
3654 TRACE("(%08x)!\n", hMidiStrm
);
3656 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3657 ret
= MMSYSERR_INVALHANDLE
;
3659 /* in case stream has been paused... FIXME is the current state correct ? */
3660 midiStreamRestart(hMidiStrm
);
3661 MMSYSTEM_MidiStream_PostMessage(lpMidiStrm
, WINE_MSM_STOP
, 0, 0);
3666 /**************************************************************************
3667 * midiStreamClose [MMSYSTEM.252]
3669 MMRESULT16 WINAPI
midiStreamClose16(HMIDISTRM16 hMidiStrm
)
3671 return midiStreamClose(hMidiStrm
);
3674 /**************************************************************************
3675 * midiStreamOpen [MMSYSTEM.251]
3677 MMRESULT16 WINAPI
midiStreamOpen16(HMIDISTRM16
* phMidiStrm
, LPUINT16 devid
,
3678 DWORD cMidi
, DWORD dwCallback
,
3679 DWORD dwInstance
, DWORD fdwOpen
)
3681 HMIDISTRM hMidiStrm32
;
3685 if (!phMidiStrm
|| !devid
)
3686 return MMSYSERR_INVALPARAM
;
3688 ret
= MMSYSTEM_MidiStream_Open(&hMidiStrm32
, &devid32
, cMidi
, dwCallback
,
3689 dwInstance
, fdwOpen
, FALSE
);
3690 *phMidiStrm
= hMidiStrm32
;
3695 /**************************************************************************
3696 * midiStreamOut [MMSYSTEM.254]
3698 MMRESULT16 WINAPI
midiStreamOut16(HMIDISTRM16 hMidiStrm
, LPMIDIHDR16 lpMidiHdr
, UINT16 cbMidiHdr
)
3700 return midiStreamOut(hMidiStrm
, (LPMIDIHDR
)lpMidiHdr
, cbMidiHdr
);
3703 /**************************************************************************
3704 * midiStreamPause [MMSYSTEM.255]
3706 MMRESULT16 WINAPI
midiStreamPause16(HMIDISTRM16 hMidiStrm
)
3708 return midiStreamPause(hMidiStrm
);
3711 /**************************************************************************
3712 * midiStreamPosition [MMSYSTEM.253]
3714 MMRESULT16 WINAPI
midiStreamPosition16(HMIDISTRM16 hMidiStrm
, LPMMTIME16 lpmmt16
, UINT16 cbmmt
)
3720 return MMSYSERR_INVALPARAM
;
3721 MMSYSTEM_MMTIME16to32(&mmt32
, lpmmt16
);
3722 ret
= midiStreamPosition(hMidiStrm
, &mmt32
, sizeof(MMTIME
));
3723 MMSYSTEM_MMTIME32to16(lpmmt16
, &mmt32
);
3727 /**************************************************************************
3728 * midiStreamProperty [MMSYSTEM.250]
3730 MMRESULT16 WINAPI
midiStreamProperty16(HMIDISTRM16 hMidiStrm
, LPBYTE lpPropData
, DWORD dwProperty
)
3732 return midiStreamProperty(hMidiStrm
, lpPropData
, dwProperty
);
3735 /**************************************************************************
3736 * midiStreamRestart [MMSYSTEM.256]
3738 MMRESULT16 WINAPI
midiStreamRestart16(HMIDISTRM16 hMidiStrm
)
3740 return midiStreamRestart(hMidiStrm
);
3743 /**************************************************************************
3744 * midiStreamStop [MMSYSTEM.257]
3746 MMRESULT16 WINAPI
midiStreamStop16(HMIDISTRM16 hMidiStrm
)
3748 return midiStreamStop(hMidiStrm
);
3751 static UINT WINAPI
MMSYSTEM_waveOpen(HANDLE
* lphndl
, UINT uDeviceID
, UINT uType
,
3752 const LPWAVEFORMATEX lpFormat
,
3753 DWORD dwCallback
, DWORD dwInstance
,
3754 DWORD dwFlags
, BOOL bFrom32
)
3758 DWORD dwRet
= MMSYSERR_NOERROR
;
3761 TRACE("(%p, %d, %s, %p, %08lX, %08lX, %08lX, %d);\n",
3762 lphndl
, (int)uDeviceID
, (uType
==MMDRV_WAVEOUT
)?"Out":"In", lpFormat
, dwCallback
,
3763 dwInstance
, dwFlags
, bFrom32
?32:16);
3765 if (dwFlags
& WAVE_FORMAT_QUERY
) TRACE("WAVE_FORMAT_QUERY requested !\n");
3767 if (lpFormat
== NULL
) return WAVERR_BADFORMAT
;
3768 if ((dwFlags
& WAVE_MAPPED
) && (uDeviceID
== (UINT
)-1))
3769 return MMSYSERR_INVALPARAM
;
3771 TRACE("wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u\n",
3772 lpFormat
->wFormatTag
, lpFormat
->nChannels
, lpFormat
->nSamplesPerSec
,
3773 lpFormat
->nAvgBytesPerSec
, lpFormat
->nBlockAlign
, lpFormat
->wBitsPerSample
, lpFormat
->cbSize
);
3775 if ((wmld
= MMDRV_Alloc(sizeof(WINE_WAVE
), uType
, &handle
,
3776 &dwFlags
, &dwCallback
, &dwInstance
, bFrom32
)) == NULL
)
3777 return MMSYSERR_NOMEM
;
3780 wod
.lpFormat
= lpFormat
; /* should the struct be copied iso pointer? */
3781 wod
.dwCallback
= dwCallback
;
3782 wod
.dwInstance
= dwInstance
;
3785 if (dwFlags
& WAVE_MAPPED
) {
3786 wod
.uMappedDeviceID
= uDeviceID
;
3787 uDeviceID
= WAVE_MAPPER
;
3789 wod
.uMappedDeviceID
= -1;
3791 wmld
->uDeviceID
= uDeviceID
;
3793 dwRet
= MMDRV_Open(wmld
, (uType
== MMDRV_WAVEOUT
) ? WODM_OPEN
: WIDM_OPEN
, (DWORD
)&wod
, dwFlags
);
3795 if ((dwFlags
& WAVE_FORMAT_QUERY
) || dwRet
!= MMSYSERR_NOERROR
) {
3796 MMDRV_Free(handle
, wmld
);
3800 if (lphndl
!= NULL
) *lphndl
= handle
;
3801 TRACE("=> %ld hWave=%04x\n", dwRet
, handle
);
3806 /**************************************************************************
3807 * waveOutGetNumDevs [WINMM.@]
3809 UINT WINAPI
waveOutGetNumDevs(void)
3811 return MMDRV_GetNum(MMDRV_WAVEOUT
);
3814 /**************************************************************************
3815 * waveOutGetNumDevs [MMSYSTEM.401]
3817 UINT16 WINAPI
waveOutGetNumDevs16(void)
3819 return MMDRV_GetNum(MMDRV_WAVEOUT
);
3822 /**************************************************************************
3823 * waveOutGetDevCaps [MMSYSTEM.402]
3825 UINT16 WINAPI
waveOutGetDevCaps16(UINT16 uDeviceID
,
3826 LPWAVEOUTCAPS16 lpCaps
, UINT16 uSize
)
3831 TRACE("(%u %p %u)!\n", uDeviceID
, lpCaps
, uSize
);
3832 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
3834 ret
= waveOutGetDevCapsA(uDeviceID
, &wocA
, sizeof(wocA
));
3836 if (ret
== MMSYSERR_NOERROR
) {
3837 lpCaps
->wMid
= wocA
.wMid
;
3838 lpCaps
->wPid
= wocA
.wPid
;
3839 lpCaps
->vDriverVersion
= wocA
.vDriverVersion
;
3840 strcpy(lpCaps
->szPname
, wocA
.szPname
);
3841 lpCaps
->dwFormats
= wocA
.dwFormats
;
3842 lpCaps
->wChannels
= wocA
.wChannels
;
3843 lpCaps
->dwSupport
= wocA
.dwSupport
;
3848 /**************************************************************************
3849 * waveOutGetDevCapsA [WINMM.@]
3851 UINT WINAPI
waveOutGetDevCapsA(UINT uDeviceID
, LPWAVEOUTCAPSA lpCaps
,
3856 TRACE("(%u %p %u)!\n", uDeviceID
, lpCaps
, uSize
);
3858 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
3860 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_WAVEOUT
, TRUE
)) == NULL
)
3861 return MMSYSERR_INVALHANDLE
;
3863 return MMDRV_Message(wmld
, WODM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
3867 /**************************************************************************
3868 * waveOutGetDevCapsW [WINMM.@]
3870 UINT WINAPI
waveOutGetDevCapsW(UINT uDeviceID
, LPWAVEOUTCAPSW lpCaps
,
3876 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
3878 ret
= waveOutGetDevCapsA(uDeviceID
, &wocA
, sizeof(wocA
));
3880 if (ret
== MMSYSERR_NOERROR
) {
3881 lpCaps
->wMid
= wocA
.wMid
;
3882 lpCaps
->wPid
= wocA
.wPid
;
3883 lpCaps
->vDriverVersion
= wocA
.vDriverVersion
;
3884 MultiByteToWideChar( CP_ACP
, 0, wocA
.szPname
, -1, lpCaps
->szPname
,
3885 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
3886 lpCaps
->dwFormats
= wocA
.dwFormats
;
3887 lpCaps
->wChannels
= wocA
.wChannels
;
3888 lpCaps
->dwSupport
= wocA
.dwSupport
;
3893 /**************************************************************************
3894 * WAVE_GetErrorText [internal]
3896 static UINT16
WAVE_GetErrorText(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
3898 UINT16 ret
= MMSYSERR_BADERRNUM
;
3900 if (lpText
== NULL
) {
3901 ret
= MMSYSERR_INVALPARAM
;
3902 } else if (uSize
== 0) {
3903 ret
= MMSYSERR_NOERROR
;
3905 /* test has been removed 'coz MMSYSERR_BASE is 0, and gcc did emit
3906 * a warning for the test was always true */
3907 (/*uError >= MMSYSERR_BASE && */uError
<= MMSYSERR_LASTERROR
) ||
3908 (uError
>= WAVERR_BASE
&& uError
<= WAVERR_LASTERROR
)) {
3910 if (LoadStringA(MULTIMEDIA_GetIData()->hWinMM32Instance
,
3911 uError
, lpText
, uSize
) > 0) {
3912 ret
= MMSYSERR_NOERROR
;
3918 /**************************************************************************
3919 * waveOutGetErrorText [MMSYSTEM.403]
3921 UINT16 WINAPI
waveOutGetErrorText16(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
3923 return WAVE_GetErrorText(uError
, lpText
, uSize
);
3926 /**************************************************************************
3927 * waveOutGetErrorTextA [WINMM.@]
3929 UINT WINAPI
waveOutGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
3931 return WAVE_GetErrorText(uError
, lpText
, uSize
);
3934 /**************************************************************************
3935 * waveOutGetErrorTextW [WINMM.@]
3937 UINT WINAPI
waveOutGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
3939 LPSTR xstr
= HeapAlloc(GetProcessHeap(), 0, uSize
);
3940 UINT ret
= WAVE_GetErrorText(uError
, xstr
, uSize
);
3942 MultiByteToWideChar( CP_ACP
, 0, xstr
, -1, lpText
, uSize
);
3943 HeapFree(GetProcessHeap(), 0, xstr
);
3947 /**************************************************************************
3948 * waveOutOpen [WINMM.@]
3949 * All the args/structs have the same layout as the win16 equivalents
3951 UINT WINAPI
waveOutOpen(HWAVEOUT
* lphWaveOut
, UINT uDeviceID
,
3952 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
3953 DWORD dwInstance
, DWORD dwFlags
)
3955 return MMSYSTEM_waveOpen(lphWaveOut
, uDeviceID
, MMDRV_WAVEOUT
, lpFormat
,
3956 dwCallback
, dwInstance
, dwFlags
, TRUE
);
3959 /**************************************************************************
3960 * waveOutOpen [MMSYSTEM.404]
3962 UINT16 WINAPI
waveOutOpen16(HWAVEOUT16
* lphWaveOut
, UINT16 uDeviceID
,
3963 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
3964 DWORD dwInstance
, DWORD dwFlags
)
3969 /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
3970 * call the 32 bit version
3971 * however, we need to promote correctly the wave mapper id
3972 * (0xFFFFFFFF and not 0x0000FFFF)
3974 ret
= MMSYSTEM_waveOpen(&hWaveOut
, (uDeviceID
== (UINT16
)-1) ? (UINT
)-1 : uDeviceID
,
3975 MMDRV_WAVEOUT
, lpFormat
, dwCallback
, dwInstance
, dwFlags
, FALSE
);
3977 if (lphWaveOut
!= NULL
) *lphWaveOut
= hWaveOut
;
3981 /**************************************************************************
3982 * waveOutClose [WINMM.@]
3984 UINT WINAPI
waveOutClose(HWAVEOUT hWaveOut
)
3989 TRACE("(%04X)\n", hWaveOut
);
3991 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
3992 return MMSYSERR_INVALHANDLE
;
3994 dwRet
= MMDRV_Close(wmld
, WODM_CLOSE
);
3995 MMDRV_Free(hWaveOut
, wmld
);
4000 /**************************************************************************
4001 * waveOutClose [MMSYSTEM.405]
4003 UINT16 WINAPI
waveOutClose16(HWAVEOUT16 hWaveOut
)
4008 ReleaseThunkLock(&level
);
4009 ret
= waveOutClose(hWaveOut
);
4010 RestoreThunkLock(level
);
4014 /**************************************************************************
4015 * waveOutPrepareHeader [WINMM.@]
4017 UINT WINAPI
waveOutPrepareHeader(HWAVEOUT hWaveOut
,
4018 WAVEHDR
* lpWaveOutHdr
, UINT uSize
)
4022 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpWaveOutHdr
, uSize
);
4024 if (lpWaveOutHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4026 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4027 return MMSYSERR_INVALHANDLE
;
4029 return MMDRV_Message(wmld
, WODM_PREPARE
, (DWORD
)lpWaveOutHdr
, uSize
, TRUE
);
4032 /**************************************************************************
4033 * waveOutPrepareHeader [MMSYSTEM.406]
4035 UINT16 WINAPI
waveOutPrepareHeader16(HWAVEOUT16 hWaveOut
, /* [in] */
4036 SEGPTR lpsegWaveOutHdr
, /* [???] */
4037 UINT16 uSize
) /* [in] */
4040 LPWAVEHDR lpWaveOutHdr
= MapSL(lpsegWaveOutHdr
);
4042 TRACE("(%04X, %08lx, %u);\n", hWaveOut
, lpsegWaveOutHdr
, uSize
);
4044 if (lpWaveOutHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4046 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4047 return MMSYSERR_INVALHANDLE
;
4049 return MMDRV_Message(wmld
, WODM_PREPARE
, (DWORD
)lpsegWaveOutHdr
, uSize
, FALSE
);
4052 /**************************************************************************
4053 * waveOutUnprepareHeader [WINMM.@]
4055 UINT WINAPI
waveOutUnprepareHeader(HWAVEOUT hWaveOut
,
4056 LPWAVEHDR lpWaveOutHdr
, UINT uSize
)
4060 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpWaveOutHdr
, uSize
);
4062 if (!(lpWaveOutHdr
->dwFlags
& WHDR_PREPARED
)) {
4063 return MMSYSERR_NOERROR
;
4066 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4067 return MMSYSERR_INVALHANDLE
;
4069 return MMDRV_Message(wmld
, WODM_UNPREPARE
, (DWORD
)lpWaveOutHdr
, uSize
, TRUE
);
4072 /**************************************************************************
4073 * waveOutUnprepareHeader [MMSYSTEM.407]
4075 UINT16 WINAPI
waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut
, /* [in] */
4076 SEGPTR lpsegWaveOutHdr
, /* [???] */
4077 UINT16 uSize
) /* [in] */
4080 LPWAVEHDR lpWaveOutHdr
= MapSL(lpsegWaveOutHdr
);
4082 TRACE("(%04X, %08lx, %u);\n", hWaveOut
, lpsegWaveOutHdr
, uSize
);
4084 if (!(lpWaveOutHdr
->dwFlags
& WHDR_PREPARED
)) {
4085 return MMSYSERR_NOERROR
;
4088 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4089 return MMSYSERR_INVALHANDLE
;
4091 return MMDRV_Message(wmld
, WODM_UNPREPARE
, (DWORD
)lpsegWaveOutHdr
, uSize
, FALSE
);
4094 /**************************************************************************
4095 * waveOutWrite [WINMM.@]
4097 UINT WINAPI
waveOutWrite(HWAVEOUT hWaveOut
, LPWAVEHDR lpWaveOutHdr
,
4102 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpWaveOutHdr
, uSize
);
4104 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4105 return MMSYSERR_INVALHANDLE
;
4107 return MMDRV_Message(wmld
, WODM_WRITE
, (DWORD
)lpWaveOutHdr
, uSize
, TRUE
);
4110 /**************************************************************************
4111 * waveOutWrite [MMSYSTEM.408]
4113 UINT16 WINAPI
waveOutWrite16(HWAVEOUT16 hWaveOut
, /* [in] */
4114 LPWAVEHDR lpsegWaveOutHdr
, /* [???] NOTE: SEGPTR */
4115 UINT16 uSize
) /* [in] */
4119 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpsegWaveOutHdr
, uSize
);
4121 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4122 return MMSYSERR_INVALHANDLE
;
4124 return MMDRV_Message(wmld
, WODM_WRITE
, (DWORD
)lpsegWaveOutHdr
, uSize
, FALSE
);
4127 /**************************************************************************
4128 * waveOutBreakLoop [WINMM.@]
4130 UINT WINAPI
waveOutBreakLoop(HWAVEOUT hWaveOut
)
4134 TRACE("(%04X);\n", hWaveOut
);
4136 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4137 return MMSYSERR_INVALHANDLE
;
4138 return MMDRV_Message(wmld
, WODM_BREAKLOOP
, 0L, 0L, TRUE
);
4141 /**************************************************************************
4142 * waveOutBreakLoop [MMSYSTEM.419]
4144 UINT16 WINAPI
waveOutBreakLoop16(HWAVEOUT16 hWaveOut16
)
4149 ReleaseThunkLock(&level
);
4150 ret
= waveOutBreakLoop(hWaveOut16
);
4151 RestoreThunkLock(level
);
4155 /**************************************************************************
4156 * waveOutPause [WINMM.@]
4158 UINT WINAPI
waveOutPause(HWAVEOUT hWaveOut
)
4162 TRACE("(%04X);\n", hWaveOut
);
4164 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4165 return MMSYSERR_INVALHANDLE
;
4166 return MMDRV_Message(wmld
, WODM_PAUSE
, 0L, 0L, TRUE
);
4169 /**************************************************************************
4170 * waveOutPause [MMSYSTEM.409]
4172 UINT16 WINAPI
waveOutPause16(HWAVEOUT16 hWaveOut16
)
4177 ReleaseThunkLock(&level
);
4178 ret
= waveOutPause(hWaveOut16
);
4179 RestoreThunkLock(level
);
4183 /**************************************************************************
4184 * waveOutReset [WINMM.@]
4186 UINT WINAPI
waveOutReset(HWAVEOUT hWaveOut
)
4190 TRACE("(%04X);\n", hWaveOut
);
4192 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4193 return MMSYSERR_INVALHANDLE
;
4194 return MMDRV_Message(wmld
, WODM_RESET
, 0L, 0L, TRUE
);
4197 /**************************************************************************
4198 * waveOutReset [MMSYSTEM.411]
4200 UINT16 WINAPI
waveOutReset16(HWAVEOUT16 hWaveOut16
)
4205 ReleaseThunkLock(&level
);
4206 ret
= waveOutReset(hWaveOut16
);
4207 RestoreThunkLock(level
);
4211 /**************************************************************************
4212 * waveOutRestart [WINMM.@]
4214 UINT WINAPI
waveOutRestart(HWAVEOUT hWaveOut
)
4218 TRACE("(%04X);\n", hWaveOut
);
4220 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4221 return MMSYSERR_INVALHANDLE
;
4222 return MMDRV_Message(wmld
, WODM_RESTART
, 0L, 0L, TRUE
);
4225 /**************************************************************************
4226 * waveOutRestart [MMSYSTEM.410]
4228 UINT16 WINAPI
waveOutRestart16(HWAVEOUT16 hWaveOut16
)
4233 ReleaseThunkLock(&level
);
4234 ret
= waveOutRestart(hWaveOut16
);
4235 RestoreThunkLock(level
);
4239 /**************************************************************************
4240 * waveOutGetPosition [WINMM.@]
4242 UINT WINAPI
waveOutGetPosition(HWAVEOUT hWaveOut
, LPMMTIME lpTime
,
4247 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpTime
, uSize
);
4249 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4250 return MMSYSERR_INVALHANDLE
;
4252 return MMDRV_Message(wmld
, WODM_GETPOS
, (DWORD
)lpTime
, uSize
, TRUE
);
4255 /**************************************************************************
4256 * waveOutGetPosition [MMSYSTEM.412]
4258 UINT16 WINAPI
waveOutGetPosition16(HWAVEOUT16 hWaveOut
, LPMMTIME16 lpTime
,
4264 mmt
.wType
= lpTime
->wType
;
4265 ret
= waveOutGetPosition(hWaveOut
, &mmt
, sizeof(mmt
));
4266 MMSYSTEM_MMTIME32to16(lpTime
, &mmt
);
4270 /**************************************************************************
4271 * waveOutGetPitch [WINMM.@]
4273 UINT WINAPI
waveOutGetPitch(HWAVEOUT hWaveOut
, LPDWORD lpdw
)
4277 TRACE("(%04X, %08lx);\n", hWaveOut
, (DWORD
)lpdw
);
4279 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4280 return MMSYSERR_INVALHANDLE
;
4281 return MMDRV_Message(wmld
, WODM_GETPITCH
, (DWORD
)lpdw
, 0L, TRUE
);
4284 /**************************************************************************
4285 * waveOutGetPitch [MMSYSTEM.413]
4287 UINT16 WINAPI
waveOutGetPitch16(HWAVEOUT16 hWaveOut16
, LPDWORD lpdw
)
4289 return waveOutGetPitch(hWaveOut16
, lpdw
);
4292 /**************************************************************************
4293 * waveOutSetPitch [WINMM.@]
4295 UINT WINAPI
waveOutSetPitch(HWAVEOUT hWaveOut
, DWORD dw
)
4299 TRACE("(%04X, %08lx);\n", hWaveOut
, (DWORD
)dw
);
4301 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4302 return MMSYSERR_INVALHANDLE
;
4303 return MMDRV_Message(wmld
, WODM_SETPITCH
, dw
, 0L, TRUE
);
4306 /**************************************************************************
4307 * waveOutSetPitch [MMSYSTEM.414]
4309 UINT16 WINAPI
waveOutSetPitch16(HWAVEOUT16 hWaveOut16
, DWORD dw
)
4311 return waveOutSetPitch(hWaveOut16
, dw
);
4314 /**************************************************************************
4315 * waveOutGetPlaybackRate [WINMM.@]
4317 UINT WINAPI
waveOutGetPlaybackRate(HWAVEOUT hWaveOut
, LPDWORD lpdw
)
4321 TRACE("(%04X, %08lx);\n", hWaveOut
, (DWORD
)lpdw
);
4323 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4324 return MMSYSERR_INVALHANDLE
;
4325 return MMDRV_Message(wmld
, WODM_GETPLAYBACKRATE
, (DWORD
)lpdw
, 0L, TRUE
);
4328 /**************************************************************************
4329 * waveOutGetPlaybackRate [MMSYSTEM.417]
4331 UINT16 WINAPI
waveOutGetPlaybackRate16(HWAVEOUT16 hWaveOut16
, LPDWORD lpdw
)
4333 return waveOutGetPlaybackRate(hWaveOut16
, lpdw
);
4336 /**************************************************************************
4337 * waveOutSetPlaybackRate [WINMM.@]
4339 UINT WINAPI
waveOutSetPlaybackRate(HWAVEOUT hWaveOut
, DWORD dw
)
4343 TRACE("(%04X, %08lx);\n", hWaveOut
, (DWORD
)dw
);
4345 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4346 return MMSYSERR_INVALHANDLE
;
4347 return MMDRV_Message(wmld
, WODM_SETPLAYBACKRATE
, dw
, 0L, TRUE
);
4350 /**************************************************************************
4351 * waveOutSetPlaybackRate [MMSYSTEM.418]
4353 UINT16 WINAPI
waveOutSetPlaybackRate16(HWAVEOUT16 hWaveOut16
, DWORD dw
)
4355 return waveOutSetPlaybackRate(hWaveOut16
, dw
);
4358 /**************************************************************************
4359 * waveOutGetVolume [WINMM.@]
4361 UINT WINAPI
waveOutGetVolume(UINT devid
, LPDWORD lpdw
)
4365 TRACE("(%04X, %08lx);\n", devid
, (DWORD
)lpdw
);
4367 if ((wmld
= MMDRV_Get(devid
, MMDRV_WAVEOUT
, TRUE
)) == NULL
)
4368 return MMSYSERR_INVALHANDLE
;
4370 return MMDRV_Message(wmld
, WODM_GETVOLUME
, (DWORD
)lpdw
, 0L, TRUE
);
4373 /**************************************************************************
4374 * waveOutGetVolume [MMSYSTEM.415]
4376 UINT16 WINAPI
waveOutGetVolume16(UINT16 devid
, LPDWORD lpdw
)
4378 return waveOutGetVolume(devid
, lpdw
);
4381 /**************************************************************************
4382 * waveOutSetVolume [WINMM.@]
4384 UINT WINAPI
waveOutSetVolume(UINT devid
, DWORD dw
)
4388 TRACE("(%04X, %08lx);\n", devid
, dw
);
4390 if ((wmld
= MMDRV_Get(devid
, MMDRV_WAVEOUT
, TRUE
)) == NULL
)
4391 return MMSYSERR_INVALHANDLE
;
4393 return MMDRV_Message(wmld
, WODM_SETVOLUME
, dw
, 0L, TRUE
);
4396 /**************************************************************************
4397 * waveOutSetVolume [MMSYSTEM.416]
4399 UINT16 WINAPI
waveOutSetVolume16(UINT16 devid
, DWORD dw
)
4401 return waveOutSetVolume(devid
, dw
);
4404 /**************************************************************************
4405 * waveOutGetID [WINMM.@]
4407 UINT WINAPI
waveOutGetID(HWAVEOUT hWaveOut
, UINT
* lpuDeviceID
)
4411 TRACE("(%04X, %p);\n", hWaveOut
, lpuDeviceID
);
4413 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
4415 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4416 return MMSYSERR_INVALHANDLE
;
4418 *lpuDeviceID
= wmld
->uDeviceID
;
4422 /**************************************************************************
4423 * waveOutGetID [MMSYSTEM.420]
4425 UINT16 WINAPI
waveOutGetID16(HWAVEOUT16 hWaveOut
, UINT16
* lpuDeviceID
)
4429 TRACE("(%04X, %p);\n", hWaveOut
, lpuDeviceID
);
4431 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
4433 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4434 return MMSYSERR_INVALHANDLE
;
4436 *lpuDeviceID
= wmld
->uDeviceID
;
4440 /**************************************************************************
4441 * waveOutMessage [WINMM.@]
4443 DWORD WINAPI
waveOutMessage(HWAVEOUT hWaveOut
, UINT uMessage
,
4444 DWORD dwParam1
, DWORD dwParam2
)
4448 TRACE("(%04x, %u, %ld, %ld)\n", hWaveOut
, uMessage
, dwParam1
, dwParam2
);
4450 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
) {
4451 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, TRUE
)) != NULL
) {
4452 return MMDRV_PhysicalFeatures(wmld
, uMessage
, dwParam1
, dwParam2
);
4454 return MMSYSERR_INVALHANDLE
;
4458 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
4459 return MMSYSERR_INVALPARAM
;
4461 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
4464 /**************************************************************************
4465 * waveOutMessage [MMSYSTEM.421]
4467 DWORD WINAPI
waveOutMessage16(HWAVEOUT16 hWaveOut
, UINT16 uMessage
,
4468 DWORD dwParam1
, DWORD dwParam2
)
4472 TRACE("(%04x, %u, %ld, %ld)\n", hWaveOut
, uMessage
, dwParam1
, dwParam2
);
4474 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
) {
4475 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, TRUE
)) != NULL
) {
4476 return MMDRV_PhysicalFeatures(wmld
, uMessage
, dwParam1
, dwParam2
);
4478 return MMSYSERR_INVALHANDLE
;
4482 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
4483 return MMSYSERR_INVALPARAM
;
4485 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, FALSE
);
4488 /**************************************************************************
4489 * waveInGetNumDevs [WINMM.@]
4491 UINT WINAPI
waveInGetNumDevs(void)
4493 return MMDRV_GetNum(MMDRV_WAVEIN
);
4496 /**************************************************************************
4497 * waveInGetNumDevs [MMSYSTEM.501]
4499 UINT16 WINAPI
waveInGetNumDevs16(void)
4501 return MMDRV_GetNum(MMDRV_WAVEIN
);
4504 /**************************************************************************
4505 * waveInGetDevCapsW [WINMM.@]
4507 UINT WINAPI
waveInGetDevCapsW(UINT uDeviceID
, LPWAVEINCAPSW lpCaps
, UINT uSize
)
4510 UINT ret
= waveInGetDevCapsA(uDeviceID
, &wicA
, uSize
);
4512 if (ret
== MMSYSERR_NOERROR
) {
4513 lpCaps
->wMid
= wicA
.wMid
;
4514 lpCaps
->wPid
= wicA
.wPid
;
4515 lpCaps
->vDriverVersion
= wicA
.vDriverVersion
;
4516 MultiByteToWideChar( CP_ACP
, 0, wicA
.szPname
, -1, lpCaps
->szPname
,
4517 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
4518 lpCaps
->dwFormats
= wicA
.dwFormats
;
4519 lpCaps
->wChannels
= wicA
.wChannels
;
4525 /**************************************************************************
4526 * waveInGetDevCapsA [WINMM.@]
4528 UINT WINAPI
waveInGetDevCapsA(UINT uDeviceID
, LPWAVEINCAPSA lpCaps
, UINT uSize
)
4532 TRACE("(%u %p %u)!\n", uDeviceID
, lpCaps
, uSize
);
4534 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_WAVEIN
, TRUE
)) == NULL
)
4535 return MMSYSERR_INVALHANDLE
;
4537 return MMDRV_Message(wmld
, WIDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
4540 /**************************************************************************
4541 * waveInGetDevCaps [MMSYSTEM.502]
4543 UINT16 WINAPI
waveInGetDevCaps16(UINT16 uDeviceID
, LPWAVEINCAPS16 lpCaps
,
4547 UINT ret
= waveInGetDevCapsA(uDeviceID
, &wicA
, sizeof(wicA
));
4549 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
4551 if (ret
== MMSYSERR_NOERROR
) {
4552 lpCaps
->wMid
= wicA
.wMid
;
4553 lpCaps
->wPid
= wicA
.wPid
;
4554 lpCaps
->vDriverVersion
= wicA
.vDriverVersion
;
4555 strcpy(lpCaps
->szPname
, wicA
.szPname
);
4556 lpCaps
->dwFormats
= wicA
.dwFormats
;
4557 lpCaps
->wChannels
= wicA
.wChannels
;
4562 /**************************************************************************
4563 * waveInGetErrorTextA [WINMM.@]
4565 UINT WINAPI
waveInGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
4567 return WAVE_GetErrorText(uError
, lpText
, uSize
);
4570 /**************************************************************************
4571 * waveInGetErrorTextW [WINMM.@]
4573 UINT WINAPI
waveInGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
4575 LPSTR txt
= HeapAlloc(GetProcessHeap(), 0, uSize
);
4576 UINT ret
= WAVE_GetErrorText(uError
, txt
, uSize
);
4578 MultiByteToWideChar( CP_ACP
, 0, txt
, -1, lpText
, uSize
);
4579 HeapFree(GetProcessHeap(), 0, txt
);
4583 /**************************************************************************
4584 * waveInGetErrorText [MMSYSTEM.503]
4586 UINT16 WINAPI
waveInGetErrorText16(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
4588 return WAVE_GetErrorText(uError
, lpText
, uSize
);
4591 /**************************************************************************
4592 * waveInOpen [WINMM.@]
4594 UINT WINAPI
waveInOpen(HWAVEIN
* lphWaveIn
, UINT uDeviceID
,
4595 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
4596 DWORD dwInstance
, DWORD dwFlags
)
4598 return MMSYSTEM_waveOpen(lphWaveIn
, uDeviceID
, MMDRV_WAVEIN
, lpFormat
,
4599 dwCallback
, dwInstance
, dwFlags
, TRUE
);
4602 /**************************************************************************
4603 * waveInOpen [MMSYSTEM.504]
4605 UINT16 WINAPI
waveInOpen16(HWAVEIN16
* lphWaveIn
, UINT16 uDeviceID
,
4606 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
4607 DWORD dwInstance
, DWORD dwFlags
)
4612 /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
4613 * call the 32 bit version
4614 * however, we need to promote correctly the wave mapper id
4615 * (0xFFFFFFFF and not 0x0000FFFF)
4617 ret
= MMSYSTEM_waveOpen(&hWaveIn
, (uDeviceID
== (UINT16
)-1) ? (UINT
)-1 : uDeviceID
,
4618 MMDRV_WAVEIN
, lpFormat
, dwCallback
, dwInstance
, dwFlags
, FALSE
);
4620 if (lphWaveIn
!= NULL
) *lphWaveIn
= hWaveIn
;
4624 /**************************************************************************
4625 * waveInClose [WINMM.@]
4627 UINT WINAPI
waveInClose(HWAVEIN hWaveIn
)
4632 TRACE("(%04X)\n", hWaveIn
);
4634 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4635 return MMSYSERR_INVALHANDLE
;
4637 dwRet
= MMDRV_Message(wmld
, WIDM_CLOSE
, 0L, 0L, TRUE
);
4638 MMDRV_Free(hWaveIn
, wmld
);
4642 /**************************************************************************
4643 * waveInClose [MMSYSTEM.505]
4645 UINT16 WINAPI
waveInClose16(HWAVEIN16 hWaveIn
)
4650 ReleaseThunkLock(&level
);
4651 ret
= waveInClose(hWaveIn
);
4652 RestoreThunkLock(level
);
4656 /**************************************************************************
4657 * waveInPrepareHeader [WINMM.@]
4659 UINT WINAPI
waveInPrepareHeader(HWAVEIN hWaveIn
, WAVEHDR
* lpWaveInHdr
,
4664 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
4666 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4667 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4668 return MMSYSERR_INVALHANDLE
;
4670 lpWaveInHdr
->dwBytesRecorded
= 0;
4672 return MMDRV_Message(wmld
, WIDM_PREPARE
, (DWORD
)lpWaveInHdr
, uSize
, TRUE
);
4675 /**************************************************************************
4676 * waveInPrepareHeader [MMSYSTEM.506]
4678 UINT16 WINAPI
waveInPrepareHeader16(HWAVEIN16 hWaveIn
, /* [in] */
4679 SEGPTR lpsegWaveInHdr
, /* [???] */
4680 UINT16 uSize
) /* [in] */
4683 LPWAVEHDR lpWaveInHdr
= MapSL(lpsegWaveInHdr
);
4686 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
4688 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALHANDLE
;
4689 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4690 return MMSYSERR_INVALHANDLE
;
4692 lpWaveInHdr
->dwBytesRecorded
= 0;
4694 ret
= MMDRV_Message(wmld
, WIDM_PREPARE
, (DWORD
)lpsegWaveInHdr
, uSize
, FALSE
);
4698 /**************************************************************************
4699 * waveInUnprepareHeader [WINMM.@]
4701 UINT WINAPI
waveInUnprepareHeader(HWAVEIN hWaveIn
, WAVEHDR
* lpWaveInHdr
,
4706 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
4708 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4709 if (!(lpWaveInHdr
->dwFlags
& WHDR_PREPARED
)) {
4710 return MMSYSERR_NOERROR
;
4713 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4714 return MMSYSERR_INVALHANDLE
;
4716 return MMDRV_Message(wmld
, WIDM_UNPREPARE
, (DWORD
)lpWaveInHdr
, uSize
, TRUE
);
4719 /**************************************************************************
4720 * waveInUnprepareHeader [MMSYSTEM.507]
4722 UINT16 WINAPI
waveInUnprepareHeader16(HWAVEIN16 hWaveIn
, /* [in] */
4723 SEGPTR lpsegWaveInHdr
, /* [???] */
4724 UINT16 uSize
) /* [in] */
4727 LPWAVEHDR lpWaveInHdr
= MapSL(lpsegWaveInHdr
);
4729 TRACE("(%04X, %08lx, %u);\n", hWaveIn
, lpsegWaveInHdr
, uSize
);
4731 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4733 if (!(lpWaveInHdr
->dwFlags
& WHDR_PREPARED
)) {
4734 return MMSYSERR_NOERROR
;
4737 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4738 return MMSYSERR_INVALHANDLE
;
4740 return MMDRV_Message(wmld
, WIDM_UNPREPARE
, (DWORD
)lpsegWaveInHdr
, uSize
, FALSE
);
4743 /**************************************************************************
4744 * waveInAddBuffer [WINMM.@]
4746 UINT WINAPI
waveInAddBuffer(HWAVEIN hWaveIn
,
4747 WAVEHDR
* lpWaveInHdr
, UINT uSize
)
4751 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
4753 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4754 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4755 return MMSYSERR_INVALHANDLE
;
4757 return MMDRV_Message(wmld
, WIDM_ADDBUFFER
, (DWORD
)lpWaveInHdr
, uSize
, TRUE
);
4760 /**************************************************************************
4761 * waveInAddBuffer [MMSYSTEM.508]
4763 UINT16 WINAPI
waveInAddBuffer16(HWAVEIN16 hWaveIn
, /* [in] */
4764 WAVEHDR
* lpsegWaveInHdr
, /* [???] NOTE: SEGPTR */
4765 UINT16 uSize
) /* [in] */
4769 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpsegWaveInHdr
, uSize
);
4771 if (lpsegWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4772 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4773 return MMSYSERR_INVALHANDLE
;
4775 return MMDRV_Message(wmld
, WIDM_ADDBUFFER
, (DWORD
)lpsegWaveInHdr
, uSize
, FALSE
);
4778 /**************************************************************************
4779 * waveInReset [WINMM.@]
4781 UINT WINAPI
waveInReset(HWAVEIN hWaveIn
)
4785 TRACE("(%04X);\n", hWaveIn
);
4787 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4788 return MMSYSERR_INVALHANDLE
;
4790 return MMDRV_Message(wmld
, WIDM_RESET
, 0L, 0L, TRUE
);
4793 /**************************************************************************
4794 * waveInReset [MMSYSTEM.511]
4796 UINT16 WINAPI
waveInReset16(HWAVEIN16 hWaveIn16
)
4801 ReleaseThunkLock(&level
);
4802 ret
= waveInReset(hWaveIn16
);
4803 RestoreThunkLock(level
);
4807 /**************************************************************************
4808 * waveInStart [WINMM.@]
4810 UINT WINAPI
waveInStart(HWAVEIN hWaveIn
)
4814 TRACE("(%04X);\n", hWaveIn
);
4816 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4817 return MMSYSERR_INVALHANDLE
;
4819 return MMDRV_Message(wmld
, WIDM_START
, 0L, 0L, TRUE
);
4822 /**************************************************************************
4823 * waveInStart [MMSYSTEM.509]
4825 UINT16 WINAPI
waveInStart16(HWAVEIN16 hWaveIn16
)
4830 ReleaseThunkLock(&level
);
4831 ret
= waveInStart(hWaveIn16
);
4832 RestoreThunkLock(level
);
4836 /**************************************************************************
4837 * waveInStop [WINMM.@]
4839 UINT WINAPI
waveInStop(HWAVEIN hWaveIn
)
4843 TRACE("(%04X);\n", hWaveIn
);
4845 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4846 return MMSYSERR_INVALHANDLE
;
4848 return MMDRV_Message(wmld
,WIDM_STOP
, 0L, 0L, TRUE
);
4851 /**************************************************************************
4852 * waveInStop [MMSYSTEM.510]
4854 UINT16 WINAPI
waveInStop16(HWAVEIN16 hWaveIn16
)
4859 ReleaseThunkLock(&level
);
4860 ret
= waveInStop(hWaveIn16
);
4861 RestoreThunkLock(level
);
4865 /**************************************************************************
4866 * waveInGetPosition [WINMM.@]
4868 UINT WINAPI
waveInGetPosition(HWAVEIN hWaveIn
, LPMMTIME lpTime
,
4873 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpTime
, uSize
);
4875 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4876 return MMSYSERR_INVALHANDLE
;
4878 return MMDRV_Message(wmld
, WIDM_GETPOS
, (DWORD
)lpTime
, uSize
, TRUE
);
4881 /**************************************************************************
4882 * waveInGetPosition [MMSYSTEM.512]
4884 UINT16 WINAPI
waveInGetPosition16(HWAVEIN16 hWaveIn
, LPMMTIME16 lpTime
,
4890 mmt
.wType
= lpTime
->wType
;
4891 ret
= waveInGetPosition(hWaveIn
, &mmt
, sizeof(mmt
));
4892 MMSYSTEM_MMTIME32to16(lpTime
, &mmt
);
4896 /**************************************************************************
4897 * waveInGetID [WINMM.@]
4899 UINT WINAPI
waveInGetID(HWAVEIN hWaveIn
, UINT
* lpuDeviceID
)
4903 TRACE("(%04X, %p);\n", hWaveIn
, lpuDeviceID
);
4905 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
4907 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4908 return MMSYSERR_INVALHANDLE
;
4910 *lpuDeviceID
= wmld
->uDeviceID
;
4911 return MMSYSERR_NOERROR
;
4914 /**************************************************************************
4915 * waveInGetID [MMSYSTEM.513]
4917 UINT16 WINAPI
waveInGetID16(HWAVEIN16 hWaveIn
, UINT16
* lpuDeviceID
)
4921 TRACE("(%04X, %p);\n", hWaveIn
, lpuDeviceID
);
4923 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
4925 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4926 return MMSYSERR_INVALHANDLE
;
4928 *lpuDeviceID
= wmld
->uDeviceID
;
4929 return MMSYSERR_NOERROR
;
4932 /**************************************************************************
4933 * waveInMessage [WINMM.@]
4935 DWORD WINAPI
waveInMessage(HWAVEIN hWaveIn
, UINT uMessage
,
4936 DWORD dwParam1
, DWORD dwParam2
)
4940 TRACE("(%04x, %u, %ld, %ld)\n", hWaveIn
, uMessage
, dwParam1
, dwParam2
);
4943 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
4944 return MMSYSERR_INVALPARAM
;
4946 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4947 return MMSYSERR_INVALHANDLE
;
4949 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
4952 /**************************************************************************
4953 * waveInMessage [MMSYSTEM.514]
4955 DWORD WINAPI
waveInMessage16(HWAVEIN16 hWaveIn
, UINT16 uMessage
,
4956 DWORD dwParam1
, DWORD dwParam2
)
4960 TRACE("(%04x, %u, %ld, %ld)\n", hWaveIn
, uMessage
, dwParam1
, dwParam2
);
4963 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
4964 return MMSYSERR_INVALPARAM
;
4966 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4967 return MMSYSERR_INVALHANDLE
;
4969 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
4972 /*#define USE_MM_TSK_WINE*/
4974 /**************************************************************************
4975 * mmTaskCreate [MMSYSTEM.900]
4977 * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
4978 * called upon creation with dwPmt as parameter.
4980 HINSTANCE16 WINAPI
mmTaskCreate16(SEGPTR spProc
, HINSTANCE16
*lphMmTask
, DWORD dwPmt
)
4985 DWORD showCmd
= 0x40002;
4988 TRACE("(%08lx, %p, %08lx);\n", spProc
, lphMmTask
, dwPmt
);
4989 /* This to work requires NE modules to be started with a binary command line
4990 * which is not currently the case. A patch exists but has never been committed.
4991 * A workaround would be to integrate code for mmtask.tsk into Wine, but
4992 * this requires tremendous work (starting with patching tools/build to
4993 * create NE executables (and not only DLLs) for builtins modules.
4996 FIXME("This is currently broken. It will fail\n");
4999 *(LPDWORD
)(cmdline
+ 1) = (DWORD
)spProc
;
5000 *(LPDWORD
)(cmdline
+ 5) = dwPmt
;
5001 *(LPDWORD
)(cmdline
+ 9) = 0;
5003 lp
.hEnvironment
= 0;
5004 lp
.cmdLine
= MapLS(cmdline
);
5005 lp
.showCmd
= MapLS(&showCmd
);
5008 #ifndef USE_MM_TSK_WINE
5009 handle
= LoadModule16("c:\\windows\\system\\mmtask.tsk", &lp
);
5011 handle
= LoadModule16("mmtask.tsk", &lp
);
5014 ret
= (handle
) ? 1 : 2;
5020 *lphMmTask
= handle
;
5022 UnMapLS( lp
.cmdLine
);
5023 UnMapLS( lp
.showCmd
);
5024 TRACE("=> 0x%04x/%d\n", handle
, ret
);
5028 #ifdef USE_MM_TSK_WINE
5029 /* C equivalent to mmtask.tsk binary content */
5030 void mmTaskEntryPoint16(LPSTR cmdLine
, WORD di
, WORD si
)
5032 int len
= cmdLine
[0x80];
5035 void (*fpProc
)(DWORD
) = MapSL(*((DWORD
*)(cmdLine
+ 1)));
5036 DWORD dwPmt
= *((DWORD
*)(cmdLine
+ 5));
5039 InitTask16(); /* FIXME: pmts / from context ? */
5042 if (SetMessageQueue16(0x40)) {
5044 if (HIWORD(fpProc
)) {
5046 /* EPP StackEnter16(); */
5058 /**************************************************************************
5059 * mmTaskBlock [MMSYSTEM.902]
5061 void WINAPI
mmTaskBlock16(HINSTANCE16 WINE_UNUSED hInst
)
5066 GetMessageA(&msg
, 0, 0, 0);
5068 TranslateMessage(&msg
);
5069 DispatchMessageA(&msg
);
5071 } while (msg
.message
< 0x3A0);
5074 /**************************************************************************
5075 * mmTaskSignal [MMSYSTEM.903]
5077 LRESULT WINAPI
mmTaskSignal16(HTASK16 ht
)
5079 TRACE("(%04x);\n", ht
);
5080 return PostAppMessage16(ht
, WM_USER
, 0, 0);
5083 /**************************************************************************
5084 * mmGetCurrentTask [MMSYSTEM.904]
5086 HTASK16 WINAPI
mmGetCurrentTask16(void)
5088 return GetCurrentTask();
5091 /**************************************************************************
5092 * mmTaskYield [MMSYSTEM.905]
5094 void WINAPI
mmTaskYield16(void)
5098 if (PeekMessageA(&msg
, 0, 0, 0, 0)) {
5103 DWORD WINAPI
GetProcessFlags(DWORD
);
5105 /**************************************************************************
5106 * mmThreadCreate [MMSYSTEM.1120]
5109 * Creates a MM thread, calling fpThreadAddr(dwPmt).
5111 * bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
5112 * bit.1 set means to open a VxD for this thread (unsupported)
5114 LRESULT WINAPI
mmThreadCreate16(FARPROC16 fpThreadAddr
, LPHANDLE lpHndl
, DWORD dwPmt
, DWORD dwFlags
)
5119 TRACE("(%p, %p, %08lx, %08lx)!\n", fpThreadAddr
, lpHndl
, dwPmt
, dwFlags
);
5121 hndl
= GlobalAlloc16(sizeof(WINE_MMTHREAD
), GMEM_SHARE
|GMEM_ZEROINIT
);
5126 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5129 /* force mmtask routines even if mmthread is required */
5130 /* this will work only if the patch about binary cmd line and NE tasks
5136 lpMMThd
->dwSignature
= WINE_MMTHREAD_CREATED
;
5137 lpMMThd
->dwCounter
= 0;
5138 lpMMThd
->hThread
= 0;
5139 lpMMThd
->dwThreadID
= 0;
5140 lpMMThd
->fpThread
= fpThreadAddr
;
5141 lpMMThd
->dwThreadPmt
= dwPmt
;
5142 lpMMThd
->dwSignalCount
= 0;
5143 lpMMThd
->hEvent
= 0;
5145 lpMMThd
->dwStatus
= 0;
5146 lpMMThd
->dwFlags
= dwFlags
;
5149 if ((dwFlags
& 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
5150 lpMMThd
->hEvent
= CreateEventA(0, 0, 1, 0);
5152 TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd
);
5153 if (lpMMThd
->dwFlags
& 2) {
5154 /* as long as we don't support MM VxD in wine, we don't need
5155 * to care about this flag
5157 /* FIXME("Don't know how to properly open VxD handles\n"); */
5158 /* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
5161 lpMMThd
->hThread
= CreateThread(0, 0, (LPTHREAD_START_ROUTINE
)WINE_mmThreadEntryPoint
,
5162 (LPVOID
)(DWORD
)hndl
, CREATE_SUSPENDED
, &lpMMThd
->dwThreadID
);
5163 if (lpMMThd
->hThread
== 0) {
5164 WARN("Couldn't create thread\n");
5165 /* clean-up(VxDhandle...); devicedirectio... */
5166 if (lpMMThd
->hEvent
!= 0)
5167 CloseHandle(lpMMThd
->hEvent
);
5170 TRACE("Got a nice thread hndl=0x%04x id=0x%08lx\n", lpMMThd
->hThread
, lpMMThd
->dwThreadID
);
5174 /* get WINE_mmThreadEntryPoint()
5175 * 2047 is its ordinal in mmsystem.spec
5177 FARPROC16 fp
= GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (LPCSTR
)2047);
5179 TRACE("farproc seg=0x%08lx lin=%p\n", (DWORD
)fp
, MapSL((SEGPTR
)fp
));
5181 ret
= (fp
== 0) ? 2 : mmTaskCreate16((DWORD
)fp
, 0, hndl
);
5185 if (lpMMThd
->hThread
&& !ResumeThread(lpMMThd
->hThread
))
5186 WARN("Couldn't resume thread\n");
5188 while (lpMMThd
->dwStatus
!= 0x10) { /* test also HIWORD of dwStatus */
5202 TRACE("ok => %ld\n", ret
);
5206 /**************************************************************************
5207 * mmThreadSignal [MMSYSTEM.1121]
5209 void WINAPI
mmThreadSignal16(HANDLE16 hndl
)
5211 TRACE("(%04x)!\n", hndl
);
5214 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5216 lpMMThd
->dwCounter
++;
5217 if (lpMMThd
->hThread
!= 0) {
5218 InterlockedIncrement(&lpMMThd
->dwSignalCount
);
5219 SetEvent(lpMMThd
->hEvent
);
5221 mmTaskSignal16(lpMMThd
->hTask
);
5223 lpMMThd
->dwCounter
--;
5227 /**************************************************************************
5228 * MMSYSTEM_ThreadBlock [internal]
5230 static void MMSYSTEM_ThreadBlock(WINE_MMTHREAD
* lpMMThd
)
5235 if (lpMMThd
->dwThreadID
!= GetCurrentThreadId())
5236 ERR("Not called by thread itself\n");
5239 ResetEvent(lpMMThd
->hEvent
);
5240 if (InterlockedDecrement(&lpMMThd
->dwSignalCount
) >= 0)
5242 InterlockedIncrement(&lpMMThd
->dwSignalCount
);
5246 ret
= MsgWaitForMultipleObjects(1, &lpMMThd
->hEvent
, FALSE
, INFINITE
, QS_ALLINPUT
);
5248 case WAIT_OBJECT_0
: /* Event */
5251 case WAIT_OBJECT_0
+ 1: /* Msg */
5253 if (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) {
5254 TranslateMessage(&msg
);
5255 DispatchMessageA(&msg
);
5259 WARN("S2.x unsupported ret val 0x%08lx\n", ret
);
5265 /**************************************************************************
5266 * mmThreadBlock [MMSYSTEM.1122]
5268 void WINAPI
mmThreadBlock16(HANDLE16 hndl
)
5270 TRACE("(%04x)!\n", hndl
);
5273 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5275 if (lpMMThd
->hThread
!= 0) {
5278 ReleaseThunkLock(&lc
);
5279 MMSYSTEM_ThreadBlock(lpMMThd
);
5280 RestoreThunkLock(lc
);
5282 mmTaskBlock16(lpMMThd
->hTask
);
5288 /**************************************************************************
5289 * mmThreadIsCurrent [MMSYSTEM.1123]
5291 BOOL16 WINAPI
mmThreadIsCurrent16(HANDLE16 hndl
)
5295 TRACE("(%04x)!\n", hndl
);
5297 if (hndl
&& mmThreadIsValid16(hndl
)) {
5298 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5299 ret
= (GetCurrentThreadId() == lpMMThd
->dwThreadID
);
5301 TRACE("=> %d\n", ret
);
5305 /**************************************************************************
5306 * mmThreadIsValid [MMSYSTEM.1124]
5308 BOOL16 WINAPI
mmThreadIsValid16(HANDLE16 hndl
)
5312 TRACE("(%04x)!\n", hndl
);
5315 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5317 if (!IsBadWritePtr(lpMMThd
, sizeof(WINE_MMTHREAD
)) &&
5318 lpMMThd
->dwSignature
== WINE_MMTHREAD_CREATED
&&
5319 IsTask16(lpMMThd
->hTask
)) {
5320 lpMMThd
->dwCounter
++;
5321 if (lpMMThd
->hThread
!= 0) {
5323 if (GetExitCodeThread(lpMMThd
->hThread
, &dwThreadRet
) &&
5324 dwThreadRet
== STATUS_PENDING
) {
5330 lpMMThd
->dwCounter
--;
5333 TRACE("=> %d\n", ret
);
5337 /**************************************************************************
5338 * mmThreadGetTask [MMSYSTEM.1125]
5340 HANDLE16 WINAPI
mmThreadGetTask16(HANDLE16 hndl
)
5344 TRACE("(%04x)\n", hndl
);
5346 if (mmThreadIsValid16(hndl
)) {
5347 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5348 ret
= lpMMThd
->hTask
;
5353 /* ### start build ### */
5354 extern LONG CALLBACK
MMSYSTEM_CallTo16_long_l (FARPROC16
,LONG
);
5355 /* ### stop build ### */
5357 /**************************************************************************
5358 * __wine_mmThreadEntryPoint (MMSYSTEM.2047)
5360 void WINAPI
WINE_mmThreadEntryPoint(DWORD _pmt
)
5362 HANDLE16 hndl
= (HANDLE16
)_pmt
;
5363 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5365 TRACE("(%04x %p)\n", hndl
, lpMMThd
);
5367 lpMMThd
->hTask
= LOWORD(GetCurrentTask());
5368 TRACE("[10-%08x] setting hTask to 0x%08x\n", lpMMThd
->hThread
, lpMMThd
->hTask
);
5369 lpMMThd
->dwStatus
= 0x10;
5370 MMSYSTEM_ThreadBlock(lpMMThd
);
5371 TRACE("[20-%08x]\n", lpMMThd
->hThread
);
5372 lpMMThd
->dwStatus
= 0x20;
5373 if (lpMMThd
->fpThread
) {
5374 MMSYSTEM_CallTo16_long_l(lpMMThd
->fpThread
, lpMMThd
->dwThreadPmt
);
5376 lpMMThd
->dwStatus
= 0x30;
5377 TRACE("[30-%08x]\n", lpMMThd
->hThread
);
5378 while (lpMMThd
->dwCounter
) {
5380 /* K32WOWYield16();*/
5382 TRACE("[XX-%08x]\n", lpMMThd
->hThread
);
5384 lpMMThd
->dwSignature
= WINE_MMTHREAD_DELETED
;
5385 /* close lpMMThread->hVxD directIO */
5386 if (lpMMThd
->hEvent
)
5387 CloseHandle(lpMMThd
->hEvent
);
5392 typedef BOOL16 (WINAPI
*MMCPLCALLBACK
)(HWND
, LPCSTR
, LPCSTR
, LPCSTR
);
5394 /**************************************************************************
5395 * mmShowMMCPLPropertySheet [MMSYSTEM.1150]
5397 BOOL16 WINAPI
mmShowMMCPLPropertySheet16(HWND hWnd
, LPCSTR lpStrDevice
,
5398 LPCSTR lpStrTab
, LPCSTR lpStrTitle
)
5403 TRACE("(%04x \"%s\" \"%s\" \"%s\")\n", hWnd
, lpStrDevice
, lpStrTab
, lpStrTitle
);
5405 hndl
= LoadLibraryA("MMSYS.CPL");
5407 MMCPLCALLBACK fp
= (MMCPLCALLBACK
)GetProcAddress(hndl
, "ShowMMCPLPropertySheet");
5410 ReleaseThunkLock(&lc
);
5411 ret
= (fp
)(hWnd
, lpStrDevice
, lpStrTab
, lpStrTitle
);
5412 RestoreThunkLock(lc
);
5420 /**************************************************************************
5421 * StackEnter [MMSYSTEM.32]
5423 void WINAPI
StackEnter16(void)
5426 /* mmsystem.dll from Win 95 does only this: so does Wine */
5431 /**************************************************************************
5432 * StackLeave [MMSYSTEM.33]
5434 void WINAPI
StackLeave16(void)
5437 /* mmsystem.dll from Win 95 does only this: so does Wine */
5442 /**************************************************************************
5443 * WMMMidiRunOnce [MMSYSTEM.8]
5445 void WINAPI
WMMMidiRunOnce16(void)
5447 FIXME("(), stub!\n");
5450 /**************************************************************************
5451 * OutputDebugStr [MMSYSTEM.30]
5453 void WINAPI
OutputDebugStr16(
5454 LPCSTR str
) /* [in] The message to be logged and given to the debugger. */
5456 OutputDebugStringA( str
);