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
))) {
552 s
.dwEventCount
= 1L; /* for first buffer */
556 left
= mmckInfo
.cksize
;
558 mmioSeek(hmmio
, mmckInfo
.dwDataOffset
, SEEK_SET
);
561 if (WaitForSingleObject(iData
->psStopEvent
, 0) == WAIT_OBJECT_0
)
566 count
= mmioRead(hmmio
, waveHdr
[index
].lpData
, min(bufsize
, left
));
567 if (count
< 1) break;
569 waveHdr
[index
].dwBufferLength
= count
;
570 waveHdr
[index
].dwFlags
&= ~WHDR_DONE
;
571 if (waveOutWrite(hWave
, &waveHdr
[index
], sizeof(WAVEHDR
)) == MMSYSERR_NOERROR
) {
573 PlaySound_WaitDone(&s
);
575 else FIXME("Couldn't play header\n");
578 } while (wps
->bLoop
);
580 PlaySound_WaitDone(&s
); /* for last buffer */
583 waveOutUnprepareHeader(hWave
, &waveHdr
[0], sizeof(WAVEHDR
));
584 waveOutUnprepareHeader(hWave
, &waveHdr
[1], sizeof(WAVEHDR
));
587 TRACE("Done playing='%s' => %s!\n", debugstr_w(wps
->pszSound
), bRet
? "ok" : "ko");
588 CloseHandle(s
.hEvent
);
589 if (waveHdr
) HeapFree(GetProcessHeap(), 0, waveHdr
);
590 if (lpWaveFormat
) HeapFree(GetProcessHeap(), 0, lpWaveFormat
);
591 if (hWave
) while (waveOutClose(hWave
) == WAVERR_STILLPLAYING
) Sleep(100);
592 if (hmmio
) mmioClose(hmmio
, 0);
599 static BOOL
MULTIMEDIA_PlaySound(const void* pszSound
, HMODULE hmod
, DWORD fdwSound
, BOOL bUnicode
)
601 WINE_PLAYSOUND
* wps
= NULL
;
602 LPWINE_MM_IDATA iData
= MULTIMEDIA_GetIData();
604 TRACE("pszSound='%p' hmod=%04X fdwSound=%08lX\n",
605 pszSound
, hmod
, fdwSound
);
607 /* FIXME? I see no difference between SND_NOWAIT and SND_NOSTOP !
608 * there could be one if several sounds can be played at once...
610 if ((fdwSound
& (SND_NOWAIT
| SND_NOSTOP
)) && iData
->lpPlaySound
!= NULL
)
613 /* alloc internal structure, if we need to play something */
614 if (pszSound
&& !(fdwSound
& SND_PURGE
))
616 if (!(wps
= PlaySound_Alloc(pszSound
, hmod
, fdwSound
, bUnicode
)))
620 EnterCriticalSection(&iData
->cs
);
621 /* since several threads can enter PlaySound in parallel, we're not
622 * sure, at this point, that another thread didn't start a new playsound
624 while (iData
->lpPlaySound
!= NULL
)
626 ResetEvent(iData
->psLastEvent
);
627 /* FIXME: doc says we have to stop all instances of pszSound if it's non
628 * NULL... as of today, we stop all playing instances */
629 SetEvent(iData
->psStopEvent
);
631 LeaveCriticalSection(&iData
->cs
);
632 WaitForSingleObject(iData
->psLastEvent
, INFINITE
);
633 EnterCriticalSection(&iData
->cs
);
635 ResetEvent(iData
->psStopEvent
);
638 if (wps
) wps
->lpNext
= iData
->lpPlaySound
;
639 iData
->lpPlaySound
= wps
;
640 LeaveCriticalSection(&iData
->cs
);
642 if (!pszSound
|| (fdwSound
& SND_PURGE
)) return TRUE
;
644 if (fdwSound
& SND_ASYNC
)
647 wps
->bLoop
= (fdwSound
& SND_LOOP
) ? TRUE
: FALSE
;
648 if (CreateThread(NULL
, 0, proc_PlaySound
, wps
, 0, &id
) != 0)
651 else return proc_PlaySound(wps
);
658 /**************************************************************************
659 * PlaySoundA [WINMM.@]
661 BOOL WINAPI
PlaySoundA(LPCSTR pszSoundA
, HMODULE hmod
, DWORD fdwSound
)
663 return MULTIMEDIA_PlaySound(pszSoundA
, hmod
, fdwSound
, FALSE
);
666 /**************************************************************************
667 * PlaySoundW [WINMM.@]
669 BOOL WINAPI
PlaySoundW(LPCWSTR pszSoundW
, HMODULE hmod
, DWORD fdwSound
)
671 return MULTIMEDIA_PlaySound(pszSoundW
, hmod
, fdwSound
, TRUE
);
674 /**************************************************************************
675 * PlaySound [MMSYSTEM.3]
677 BOOL16 WINAPI
PlaySound16(LPCSTR pszSound
, HMODULE16 hmod
, DWORD fdwSound
)
682 ReleaseThunkLock(&lc
);
683 retv
= PlaySoundA(pszSound
, hmod
, fdwSound
);
684 RestoreThunkLock(lc
);
689 /**************************************************************************
690 * sndPlaySoundA [WINMM.@]
692 BOOL WINAPI
sndPlaySoundA(LPCSTR pszSoundA
, UINT uFlags
)
694 uFlags
&= SND_ASYNC
|SND_LOOP
|SND_MEMORY
|SND_NODEFAULT
|SND_NOSTOP
|SND_SYNC
;
695 return MULTIMEDIA_PlaySound(pszSoundA
, 0, uFlags
, FALSE
);
698 /**************************************************************************
699 * sndPlaySoundW [WINMM.@]
701 BOOL WINAPI
sndPlaySoundW(LPCWSTR pszSound
, UINT uFlags
)
703 uFlags
&= SND_ASYNC
|SND_LOOP
|SND_MEMORY
|SND_NODEFAULT
|SND_NOSTOP
|SND_SYNC
;
704 return MULTIMEDIA_PlaySound(pszSound
, 0, uFlags
, TRUE
);
707 /**************************************************************************
708 * sndPlaySound [MMSYSTEM.2]
710 BOOL16 WINAPI
sndPlaySound16(LPCSTR lpszSoundName
, UINT16 uFlags
)
715 ReleaseThunkLock(&lc
);
716 retv
= sndPlaySoundA(lpszSoundName
, uFlags
);
717 RestoreThunkLock(lc
);
722 /**************************************************************************
723 * mmsystemGetVersion [MMSYSTEM.5]
724 * return value borrowed from Win95 winmm.dll ;)
726 UINT16 WINAPI
mmsystemGetVersion16(void)
728 return mmsystemGetVersion();
731 /**************************************************************************
732 * mmsystemGetVersion [WINMM.@]
734 UINT WINAPI
mmsystemGetVersion(void)
736 TRACE("3.10 (Win95?)\n");
740 /**************************************************************************
741 * DriverCallback [WINMM.@]
743 BOOL WINAPI
DriverCallback(DWORD dwCallBack
, UINT uFlags
, HDRVR hDev
,
744 UINT wMsg
, DWORD dwUser
, DWORD dwParam1
,
747 TRACE("(%08lX, %04X, %04X, %04X, %08lX, %08lX, %08lX); !\n",
748 dwCallBack
, uFlags
, hDev
, wMsg
, dwUser
, dwParam1
, dwParam2
);
750 switch (uFlags
& DCB_TYPEMASK
) {
754 WARN("uFlags=%04X has null DCB value, but dwCallBack=%08lX is not null !\n", uFlags
, dwCallBack
);
757 TRACE("Window(%04lX) handle=%04X!\n", dwCallBack
, hDev
);
758 PostMessageA((HWND
)dwCallBack
, wMsg
, hDev
, dwParam1
);
760 case DCB_TASK
: /* aka DCB_THREAD */
761 TRACE("Task(%04lx) !\n", dwCallBack
);
762 PostThreadMessageA(dwCallBack
, wMsg
, hDev
, dwParam1
);
765 TRACE("Function (32 bit) !\n");
766 ((LPDRVCALLBACK
)dwCallBack
)(hDev
, wMsg
, dwUser
, dwParam1
, dwParam2
);
769 TRACE("Event(%08lx) !\n", dwCallBack
);
770 SetEvent((HANDLE
)dwCallBack
);
772 case 6: /* I would dub it DCB_MMTHREADSIGNAL */
773 /* this is an undocumented DCB_ value used for mmThreads
774 * loword of dwCallBack contains the handle of the lpMMThd block
775 * which dwSignalCount has to be incremented
778 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(LOWORD(dwCallBack
), 0) );
780 TRACE("mmThread (%04x, %p) !\n", LOWORD(dwCallBack
), lpMMThd
);
781 /* same as mmThreadSignal16 */
782 InterlockedIncrement(&lpMMThd
->dwSignalCount
);
783 SetEvent(lpMMThd
->hEvent
);
784 /* some other stuff on lpMMThd->hVxD */
789 /* this is an undocumented DCB_ value for... I don't know */
793 WARN("Unknown callback type %d\n", uFlags
& DCB_TYPEMASK
);
800 /**************************************************************************
801 * DriverCallback [MMSYSTEM.31]
803 BOOL16 WINAPI
DriverCallback16(DWORD dwCallBack
, UINT16 uFlags
, HDRVR16 hDev
,
804 WORD wMsg
, DWORD dwUser
, DWORD dwParam1
,
807 return DriverCallback(dwCallBack
, uFlags
, hDev
, wMsg
, dwUser
, dwParam1
, dwParam2
);
810 /**************************************************************************
811 * Mixer devices. New to Win95
814 /**************************************************************************
815 * find out the real mixer ID depending on hmix (depends on dwFlags)
817 static LPWINE_MIXER
MIXER_GetDev(HMIXEROBJ hmix
, DWORD dwFlags
)
819 LPWINE_MIXER lpwm
= NULL
;
821 switch (dwFlags
& 0xF0000000ul
) {
822 case MIXER_OBJECTF_MIXER
:
823 lpwm
= (LPWINE_MIXER
)MMDRV_Get(hmix
, MMDRV_MIXER
, TRUE
);
825 case MIXER_OBJECTF_HMIXER
:
826 lpwm
= (LPWINE_MIXER
)MMDRV_Get(hmix
, MMDRV_MIXER
, FALSE
);
828 case MIXER_OBJECTF_WAVEOUT
:
829 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEOUT
, TRUE
, MMDRV_MIXER
);
831 case MIXER_OBJECTF_HWAVEOUT
:
832 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEOUT
, FALSE
, MMDRV_MIXER
);
834 case MIXER_OBJECTF_WAVEIN
:
835 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEIN
, TRUE
, MMDRV_MIXER
);
837 case MIXER_OBJECTF_HWAVEIN
:
838 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEIN
, FALSE
, MMDRV_MIXER
);
840 case MIXER_OBJECTF_MIDIOUT
:
841 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIOUT
, TRUE
, MMDRV_MIXER
);
843 case MIXER_OBJECTF_HMIDIOUT
:
844 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIOUT
, FALSE
, MMDRV_MIXER
);
846 case MIXER_OBJECTF_MIDIIN
:
847 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIIN
, TRUE
, MMDRV_MIXER
);
849 case MIXER_OBJECTF_HMIDIIN
:
850 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIIN
, FALSE
, MMDRV_MIXER
);
852 case MIXER_OBJECTF_AUX
:
853 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_AUX
, TRUE
, MMDRV_MIXER
);
856 FIXME("Unsupported flag (%08lx)\n", dwFlags
& 0xF0000000ul
);
862 /**************************************************************************
863 * mixerGetNumDevs [WINMM.@]
865 UINT WINAPI
mixerGetNumDevs(void)
867 return MMDRV_GetNum(MMDRV_MIXER
);
870 /**************************************************************************
871 * mixerGetNumDevs [MMSYSTEM.800]
873 UINT16 WINAPI
mixerGetNumDevs16(void)
875 return MMDRV_GetNum(MMDRV_MIXER
);
878 /**************************************************************************
879 * mixerGetDevCapsA [WINMM.@]
881 UINT WINAPI
mixerGetDevCapsA(UINT devid
, LPMIXERCAPSA mixcaps
, UINT size
)
885 if ((wmld
= MMDRV_Get(devid
, MMDRV_MIXER
, TRUE
)) == NULL
)
886 return MMSYSERR_BADDEVICEID
;
888 return MMDRV_Message(wmld
, MXDM_GETDEVCAPS
, (DWORD
)mixcaps
, size
, TRUE
);
891 /**************************************************************************
892 * mixerGetDevCapsW [WINMM.@]
894 UINT WINAPI
mixerGetDevCapsW(UINT devid
, LPMIXERCAPSW mixcaps
, UINT size
)
897 UINT ret
= mixerGetDevCapsA(devid
, &micA
, sizeof(micA
));
899 if (ret
== MMSYSERR_NOERROR
) {
900 mixcaps
->wMid
= micA
.wMid
;
901 mixcaps
->wPid
= micA
.wPid
;
902 mixcaps
->vDriverVersion
= micA
.vDriverVersion
;
903 MultiByteToWideChar( CP_ACP
, 0, micA
.szPname
, -1, mixcaps
->szPname
,
904 sizeof(mixcaps
->szPname
)/sizeof(WCHAR
) );
905 mixcaps
->fdwSupport
= micA
.fdwSupport
;
906 mixcaps
->cDestinations
= micA
.cDestinations
;
911 /**************************************************************************
912 * mixerGetDevCaps [MMSYSTEM.801]
914 UINT16 WINAPI
mixerGetDevCaps16(UINT16 devid
, LPMIXERCAPS16 mixcaps
,
918 UINT ret
= mixerGetDevCapsA(devid
, &micA
, sizeof(micA
));
920 if (ret
== MMSYSERR_NOERROR
) {
921 mixcaps
->wMid
= micA
.wMid
;
922 mixcaps
->wPid
= micA
.wPid
;
923 mixcaps
->vDriverVersion
= micA
.vDriverVersion
;
924 strcpy(mixcaps
->szPname
, micA
.szPname
);
925 mixcaps
->fdwSupport
= micA
.fdwSupport
;
926 mixcaps
->cDestinations
= micA
.cDestinations
;
931 static UINT
MMSYSTEM_mixerOpen(LPHMIXER lphMix
, UINT uDeviceID
, DWORD dwCallback
,
932 DWORD dwInstance
, DWORD fdwOpen
, BOOL bFrom32
)
939 TRACE("(%p, %d, %08lx, %08lx, %08lx)\n",
940 lphMix
, uDeviceID
, dwCallback
, dwInstance
, fdwOpen
);
942 wmld
= MMDRV_Alloc(sizeof(WINE_MIXER
), MMDRV_MIXER
, &hMix
, &fdwOpen
,
943 &dwCallback
, &dwInstance
, bFrom32
);
945 wmld
->uDeviceID
= uDeviceID
;
947 mod
.dwCallback
= dwCallback
;
948 mod
.dwInstance
= dwInstance
;
950 dwRet
= MMDRV_Open(wmld
, MXDM_OPEN
, (DWORD
)&mod
, fdwOpen
);
952 if (dwRet
!= MMSYSERR_NOERROR
) {
953 MMDRV_Free(hMix
, wmld
);
956 if (lphMix
) *lphMix
= hMix
;
957 TRACE("=> %ld hMixer=%04x\n", dwRet
, hMix
);
962 /**************************************************************************
963 * mixerOpen [WINMM.@]
965 UINT WINAPI
mixerOpen(LPHMIXER lphMix
, UINT uDeviceID
, DWORD dwCallback
,
966 DWORD dwInstance
, DWORD fdwOpen
)
968 return MMSYSTEM_mixerOpen(lphMix
, uDeviceID
,
969 dwCallback
, dwInstance
, fdwOpen
, TRUE
);
972 /**************************************************************************
973 * mixerOpen [MMSYSTEM.802]
975 UINT16 WINAPI
mixerOpen16(LPHMIXER16 lphmix
, UINT16 uDeviceID
, DWORD dwCallback
,
976 DWORD dwInstance
, DWORD fdwOpen
)
981 ret
= MMSYSTEM_mixerOpen(&hmix
, uDeviceID
,
982 dwCallback
, dwInstance
, fdwOpen
, FALSE
);
983 if (lphmix
) *lphmix
= hmix
;
987 /**************************************************************************
988 * mixerClose [WINMM.@]
990 UINT WINAPI
mixerClose(HMIXER hMix
)
995 TRACE("(%04x)\n", hMix
);
997 if ((wmld
= MMDRV_Get(hMix
, MMDRV_MIXER
, FALSE
)) == NULL
) return MMSYSERR_INVALHANDLE
;
999 dwRet
= MMDRV_Close(wmld
, MXDM_CLOSE
);
1000 MMDRV_Free(hMix
, wmld
);
1005 /**************************************************************************
1006 * mixerClose [MMSYSTEM.803]
1008 UINT16 WINAPI
mixerClose16(HMIXER16 hMix
)
1010 return mixerClose(hMix
);
1013 /**************************************************************************
1014 * mixerGetID [WINMM.@]
1016 UINT WINAPI
mixerGetID(HMIXEROBJ hmix
, LPUINT lpid
, DWORD fdwID
)
1020 TRACE("(%04x %p %08lx)\n", hmix
, lpid
, fdwID
);
1022 if ((lpwm
= MIXER_GetDev(hmix
, fdwID
)) == NULL
) {
1023 return MMSYSERR_INVALHANDLE
;
1027 *lpid
= lpwm
->mld
.uDeviceID
;
1029 return MMSYSERR_NOERROR
;
1032 /**************************************************************************
1033 * mixerGetID (MMSYSTEM.806)
1035 UINT16 WINAPI
mixerGetID16(HMIXEROBJ16 hmix
, LPUINT16 lpid
, DWORD fdwID
)
1038 UINT ret
= mixerGetID(hmix
, &xid
, fdwID
);
1045 /**************************************************************************
1046 * mixerGetControlDetailsA [WINMM.@]
1048 UINT WINAPI
mixerGetControlDetailsA(HMIXEROBJ hmix
, LPMIXERCONTROLDETAILS lpmcdA
,
1053 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcdA
, fdwDetails
);
1055 if ((lpwm
= MIXER_GetDev(hmix
, fdwDetails
)) == NULL
)
1056 return MMSYSERR_INVALHANDLE
;
1058 if (lpmcdA
== NULL
|| lpmcdA
->cbStruct
!= sizeof(*lpmcdA
))
1059 return MMSYSERR_INVALPARAM
;
1061 return MMDRV_Message(&lpwm
->mld
, MXDM_GETCONTROLDETAILS
, (DWORD
)lpmcdA
,
1065 /**************************************************************************
1066 * mixerGetControlDetailsW [WINMM.@]
1068 UINT WINAPI
mixerGetControlDetailsW(HMIXEROBJ hmix
, LPMIXERCONTROLDETAILS lpmcd
, DWORD fdwDetails
)
1070 DWORD ret
= MMSYSERR_NOTENABLED
;
1072 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcd
, fdwDetails
);
1074 if (lpmcd
== NULL
|| lpmcd
->cbStruct
!= sizeof(*lpmcd
))
1075 return MMSYSERR_INVALPARAM
;
1077 switch (fdwDetails
& MIXER_GETCONTROLDETAILSF_QUERYMASK
) {
1078 case MIXER_GETCONTROLDETAILSF_VALUE
:
1079 /* can savely use W structure as it is, no string inside */
1080 ret
= mixerGetControlDetailsA(hmix
, lpmcd
, fdwDetails
);
1082 case MIXER_GETCONTROLDETAILSF_LISTTEXT
:
1084 MIXERCONTROLDETAILS_LISTTEXTW
*pDetailsW
= (MIXERCONTROLDETAILS_LISTTEXTW
*)lpmcd
->paDetails
;
1085 MIXERCONTROLDETAILS_LISTTEXTA
*pDetailsA
;
1086 int size
= max(1, lpmcd
->cChannels
) * sizeof(MIXERCONTROLDETAILS_LISTTEXTA
);
1089 if (lpmcd
->u
.cMultipleItems
!= 0) {
1090 size
*= lpmcd
->u
.cMultipleItems
;
1092 pDetailsA
= (MIXERCONTROLDETAILS_LISTTEXTA
*)HeapAlloc(GetProcessHeap(), 0, size
);
1093 lpmcd
->paDetails
= pDetailsA
;
1094 lpmcd
->cbDetails
= sizeof(MIXERCONTROLDETAILS_LISTTEXTA
);
1095 /* set up lpmcd->paDetails */
1096 ret
= mixerGetControlDetailsA(hmix
, lpmcd
, fdwDetails
);
1097 /* copy from lpmcd->paDetails back to paDetailsW; */
1098 if(ret
== MMSYSERR_NOERROR
) {
1099 for(i
=0;i
<lpmcd
->u
.cMultipleItems
*lpmcd
->cChannels
;i
++) {
1100 pDetailsW
->dwParam1
= pDetailsA
->dwParam1
;
1101 pDetailsW
->dwParam2
= pDetailsA
->dwParam2
;
1102 MultiByteToWideChar( CP_ACP
, 0, pDetailsA
->szName
, -1,
1104 sizeof(pDetailsW
->szName
)/sizeof(WCHAR
) );
1108 pDetailsA
-= lpmcd
->u
.cMultipleItems
*lpmcd
->cChannels
;
1109 pDetailsW
-= lpmcd
->u
.cMultipleItems
*lpmcd
->cChannels
;
1111 HeapFree(GetProcessHeap(), 0, pDetailsA
);
1112 lpmcd
->paDetails
= pDetailsW
;
1113 lpmcd
->cbDetails
= sizeof(MIXERCONTROLDETAILS_LISTTEXTW
);
1117 ERR("Unsupported fdwDetails=0x%08lx\n", fdwDetails
);
1123 /**************************************************************************
1124 * mixerGetControlDetails [MMSYSTEM.808]
1126 UINT16 WINAPI
mixerGetControlDetails16(HMIXEROBJ16 hmix
,
1127 LPMIXERCONTROLDETAILS16 lpmcd
,
1130 DWORD ret
= MMSYSERR_NOTENABLED
;
1133 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcd
, fdwDetails
);
1135 if (lpmcd
== NULL
|| lpmcd
->cbStruct
!= sizeof(*lpmcd
))
1136 return MMSYSERR_INVALPARAM
;
1138 sppaDetails
= (SEGPTR
)lpmcd
->paDetails
;
1139 lpmcd
->paDetails
= MapSL(sppaDetails
);
1140 ret
= mixerGetControlDetailsA(hmix
, (LPMIXERCONTROLDETAILS
)lpmcd
, fdwDetails
);
1141 lpmcd
->paDetails
= (LPVOID
)sppaDetails
;
1146 /**************************************************************************
1147 * mixerGetLineControlsA [WINMM.@]
1149 UINT WINAPI
mixerGetLineControlsA(HMIXEROBJ hmix
, LPMIXERLINECONTROLSA lpmlcA
,
1154 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmlcA
, fdwControls
);
1156 if ((lpwm
= MIXER_GetDev(hmix
, fdwControls
)) == NULL
)
1157 return MMSYSERR_INVALHANDLE
;
1159 if (lpmlcA
== NULL
|| lpmlcA
->cbStruct
!= sizeof(*lpmlcA
))
1160 return MMSYSERR_INVALPARAM
;
1162 return MMDRV_Message(&lpwm
->mld
, MXDM_GETLINECONTROLS
, (DWORD
)lpmlcA
,
1166 /**************************************************************************
1167 * mixerGetLineControlsW [WINMM.@]
1169 UINT WINAPI
mixerGetLineControlsW(HMIXEROBJ hmix
, LPMIXERLINECONTROLSW lpmlcW
,
1172 MIXERLINECONTROLSA mlcA
;
1176 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmlcW
, fdwControls
);
1178 if (lpmlcW
== NULL
|| lpmlcW
->cbStruct
!= sizeof(*lpmlcW
) ||
1179 lpmlcW
->cbmxctrl
!= sizeof(MIXERCONTROLW
))
1180 return MMSYSERR_INVALPARAM
;
1182 mlcA
.cbStruct
= sizeof(mlcA
);
1183 mlcA
.dwLineID
= lpmlcW
->dwLineID
;
1184 mlcA
.u
.dwControlID
= lpmlcW
->u
.dwControlID
;
1185 mlcA
.u
.dwControlType
= lpmlcW
->u
.dwControlType
;
1186 mlcA
.cControls
= lpmlcW
->cControls
;
1187 mlcA
.cbmxctrl
= sizeof(MIXERCONTROLA
);
1188 mlcA
.pamxctrl
= HeapAlloc(GetProcessHeap(), 0,
1189 mlcA
.cControls
* mlcA
.cbmxctrl
);
1191 ret
= mixerGetLineControlsA(hmix
, &mlcA
, fdwControls
);
1193 if (ret
== MMSYSERR_NOERROR
) {
1194 lpmlcW
->dwLineID
= mlcA
.dwLineID
;
1195 lpmlcW
->u
.dwControlID
= mlcA
.u
.dwControlID
;
1196 lpmlcW
->u
.dwControlType
= mlcA
.u
.dwControlType
;
1197 lpmlcW
->cControls
= mlcA
.cControls
;
1199 for (i
= 0; i
< mlcA
.cControls
; i
++) {
1200 lpmlcW
->pamxctrl
[i
].cbStruct
= sizeof(MIXERCONTROLW
);
1201 lpmlcW
->pamxctrl
[i
].dwControlID
= mlcA
.pamxctrl
[i
].dwControlID
;
1202 lpmlcW
->pamxctrl
[i
].dwControlType
= mlcA
.pamxctrl
[i
].dwControlType
;
1203 lpmlcW
->pamxctrl
[i
].fdwControl
= mlcA
.pamxctrl
[i
].fdwControl
;
1204 lpmlcW
->pamxctrl
[i
].cMultipleItems
= mlcA
.pamxctrl
[i
].cMultipleItems
;
1205 MultiByteToWideChar( CP_ACP
, 0, mlcA
.pamxctrl
[i
].szShortName
, -1,
1206 lpmlcW
->pamxctrl
[i
].szShortName
,
1207 sizeof(lpmlcW
->pamxctrl
[i
].szShortName
)/sizeof(WCHAR
) );
1208 MultiByteToWideChar( CP_ACP
, 0, mlcA
.pamxctrl
[i
].szName
, -1,
1209 lpmlcW
->pamxctrl
[i
].szName
,
1210 sizeof(lpmlcW
->pamxctrl
[i
].szName
)/sizeof(WCHAR
) );
1211 /* sizeof(lpmlcW->pamxctrl[i].Bounds) ==
1212 * sizeof(mlcA.pamxctrl[i].Bounds) */
1213 memcpy(&lpmlcW
->pamxctrl
[i
].Bounds
, &mlcA
.pamxctrl
[i
].Bounds
,
1214 sizeof(mlcA
.pamxctrl
[i
].Bounds
));
1215 /* sizeof(lpmlcW->pamxctrl[i].Metrics) ==
1216 * sizeof(mlcA.pamxctrl[i].Metrics) */
1217 memcpy(&lpmlcW
->pamxctrl
[i
].Metrics
, &mlcA
.pamxctrl
[i
].Metrics
,
1218 sizeof(mlcA
.pamxctrl
[i
].Metrics
));
1222 HeapFree(GetProcessHeap(), 0, mlcA
.pamxctrl
);
1227 /**************************************************************************
1228 * mixerGetLineControls [MMSYSTEM.807]
1230 UINT16 WINAPI
mixerGetLineControls16(HMIXEROBJ16 hmix
,
1231 LPMIXERLINECONTROLS16 lpmlc16
,
1234 MIXERLINECONTROLSA mlcA
;
1237 LPMIXERCONTROL16 lpmc16
;
1239 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmlc16
, fdwControls
);
1241 if (lpmlc16
== NULL
|| lpmlc16
->cbStruct
!= sizeof(*lpmlc16
) ||
1242 lpmlc16
->cbmxctrl
!= sizeof(MIXERCONTROL16
))
1243 return MMSYSERR_INVALPARAM
;
1245 mlcA
.cbStruct
= sizeof(mlcA
);
1246 mlcA
.dwLineID
= lpmlc16
->dwLineID
;
1247 mlcA
.u
.dwControlID
= lpmlc16
->u
.dwControlID
;
1248 mlcA
.u
.dwControlType
= lpmlc16
->u
.dwControlType
;
1249 mlcA
.cControls
= lpmlc16
->cControls
;
1250 mlcA
.cbmxctrl
= sizeof(MIXERCONTROLA
);
1251 mlcA
.pamxctrl
= HeapAlloc(GetProcessHeap(), 0,
1252 mlcA
.cControls
* mlcA
.cbmxctrl
);
1254 ret
= mixerGetLineControlsA(hmix
, &mlcA
, fdwControls
);
1256 if (ret
== MMSYSERR_NOERROR
) {
1257 lpmlc16
->dwLineID
= mlcA
.dwLineID
;
1258 lpmlc16
->u
.dwControlID
= mlcA
.u
.dwControlID
;
1259 lpmlc16
->u
.dwControlType
= mlcA
.u
.dwControlType
;
1260 lpmlc16
->cControls
= mlcA
.cControls
;
1262 lpmc16
= MapSL(lpmlc16
->pamxctrl
);
1264 for (i
= 0; i
< mlcA
.cControls
; i
++) {
1265 lpmc16
[i
].cbStruct
= sizeof(MIXERCONTROL16
);
1266 lpmc16
[i
].dwControlID
= mlcA
.pamxctrl
[i
].dwControlID
;
1267 lpmc16
[i
].dwControlType
= mlcA
.pamxctrl
[i
].dwControlType
;
1268 lpmc16
[i
].fdwControl
= mlcA
.pamxctrl
[i
].fdwControl
;
1269 lpmc16
[i
].cMultipleItems
= mlcA
.pamxctrl
[i
].cMultipleItems
;
1270 strcpy(lpmc16
[i
].szShortName
, mlcA
.pamxctrl
[i
].szShortName
);
1271 strcpy(lpmc16
[i
].szName
, mlcA
.pamxctrl
[i
].szName
);
1272 /* sizeof(lpmc16[i].Bounds) == sizeof(mlcA.pamxctrl[i].Bounds) */
1273 memcpy(&lpmc16
[i
].Bounds
, &mlcA
.pamxctrl
[i
].Bounds
,
1274 sizeof(mlcA
.pamxctrl
[i
].Bounds
));
1275 /* sizeof(lpmc16[i].Metrics) == sizeof(mlcA.pamxctrl[i].Metrics) */
1276 memcpy(&lpmc16
[i
].Metrics
, &mlcA
.pamxctrl
[i
].Metrics
,
1277 sizeof(mlcA
.pamxctrl
[i
].Metrics
));
1281 HeapFree(GetProcessHeap(), 0, mlcA
.pamxctrl
);
1286 /**************************************************************************
1287 * mixerGetLineInfoA [WINMM.@]
1289 UINT WINAPI
mixerGetLineInfoA(HMIXEROBJ hmix
, LPMIXERLINEA lpmliW
, DWORD fdwInfo
)
1293 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmliW
, fdwInfo
);
1295 if ((lpwm
= MIXER_GetDev(hmix
, fdwInfo
)) == NULL
)
1296 return MMSYSERR_INVALHANDLE
;
1298 return MMDRV_Message(&lpwm
->mld
, MXDM_GETLINEINFO
, (DWORD
)lpmliW
,
1302 /**************************************************************************
1303 * mixerGetLineInfoW [WINMM.@]
1305 UINT WINAPI
mixerGetLineInfoW(HMIXEROBJ hmix
, LPMIXERLINEW lpmliW
,
1311 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmliW
, fdwInfo
);
1313 if (lpmliW
== NULL
|| lpmliW
->cbStruct
!= sizeof(*lpmliW
))
1314 return MMSYSERR_INVALPARAM
;
1316 mliA
.cbStruct
= sizeof(mliA
);
1317 switch (fdwInfo
& MIXER_GETLINEINFOF_QUERYMASK
) {
1318 case MIXER_GETLINEINFOF_COMPONENTTYPE
:
1319 mliA
.dwComponentType
= lpmliW
->dwComponentType
;
1321 case MIXER_GETLINEINFOF_DESTINATION
:
1322 mliA
.dwDestination
= lpmliW
->dwDestination
;
1324 case MIXER_GETLINEINFOF_LINEID
:
1325 mliA
.dwLineID
= lpmliW
->dwLineID
;
1327 case MIXER_GETLINEINFOF_SOURCE
:
1328 mliA
.dwDestination
= lpmliW
->dwDestination
;
1329 mliA
.dwSource
= lpmliW
->dwSource
;
1331 case MIXER_GETLINEINFOF_TARGETTYPE
:
1332 mliA
.Target
.dwType
= lpmliW
->Target
.dwType
;
1333 mliA
.Target
.wMid
= lpmliW
->Target
.wMid
;
1334 mliA
.Target
.wPid
= lpmliW
->Target
.wPid
;
1335 mliA
.Target
.vDriverVersion
= lpmliW
->Target
.vDriverVersion
;
1336 WideCharToMultiByte( CP_ACP
, 0, lpmliW
->Target
.szPname
, -1, mliA
.Target
.szPname
, sizeof(mliA
.Target
.szPname
), NULL
, NULL
);
1339 FIXME("Unsupported fdwControls=0x%08lx\n", fdwInfo
);
1342 ret
= mixerGetLineInfoA(hmix
, &mliA
, fdwInfo
);
1344 lpmliW
->dwDestination
= mliA
.dwDestination
;
1345 lpmliW
->dwSource
= mliA
.dwSource
;
1346 lpmliW
->dwLineID
= mliA
.dwLineID
;
1347 lpmliW
->fdwLine
= mliA
.fdwLine
;
1348 lpmliW
->dwUser
= mliA
.dwUser
;
1349 lpmliW
->dwComponentType
= mliA
.dwComponentType
;
1350 lpmliW
->cChannels
= mliA
.cChannels
;
1351 lpmliW
->cConnections
= mliA
.cConnections
;
1352 lpmliW
->cControls
= mliA
.cControls
;
1353 MultiByteToWideChar( CP_ACP
, 0, mliA
.szShortName
, -1, lpmliW
->szShortName
,
1354 sizeof(lpmliW
->szShortName
)/sizeof(WCHAR
) );
1355 MultiByteToWideChar( CP_ACP
, 0, mliA
.szName
, -1, lpmliW
->szName
,
1356 sizeof(lpmliW
->szName
)/sizeof(WCHAR
) );
1357 lpmliW
->Target
.dwType
= mliA
.Target
.dwType
;
1358 lpmliW
->Target
.dwDeviceID
= mliA
.Target
.dwDeviceID
;
1359 lpmliW
->Target
.wMid
= mliA
.Target
.wMid
;
1360 lpmliW
->Target
.wPid
= mliA
.Target
.wPid
;
1361 lpmliW
->Target
.vDriverVersion
= mliA
.Target
.vDriverVersion
;
1362 MultiByteToWideChar( CP_ACP
, 0, mliA
.Target
.szPname
, -1, lpmliW
->Target
.szPname
,
1363 sizeof(lpmliW
->Target
.szPname
)/sizeof(WCHAR
) );
1368 /**************************************************************************
1369 * mixerGetLineInfo [MMSYSTEM.805]
1371 UINT16 WINAPI
mixerGetLineInfo16(HMIXEROBJ16 hmix
, LPMIXERLINE16 lpmli16
,
1377 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmli16
, fdwInfo
);
1379 if (lpmli16
== NULL
|| lpmli16
->cbStruct
!= sizeof(*lpmli16
))
1380 return MMSYSERR_INVALPARAM
;
1382 mliA
.cbStruct
= sizeof(mliA
);
1383 switch (fdwInfo
& MIXER_GETLINEINFOF_QUERYMASK
) {
1384 case MIXER_GETLINEINFOF_COMPONENTTYPE
:
1385 mliA
.dwComponentType
= lpmli16
->dwComponentType
;
1387 case MIXER_GETLINEINFOF_DESTINATION
:
1388 mliA
.dwDestination
= lpmli16
->dwDestination
;
1390 case MIXER_GETLINEINFOF_LINEID
:
1391 mliA
.dwLineID
= lpmli16
->dwLineID
;
1393 case MIXER_GETLINEINFOF_SOURCE
:
1394 mliA
.dwDestination
= lpmli16
->dwDestination
;
1395 mliA
.dwSource
= lpmli16
->dwSource
;
1397 case MIXER_GETLINEINFOF_TARGETTYPE
:
1398 mliA
.Target
.dwType
= lpmli16
->Target
.dwType
;
1399 mliA
.Target
.wMid
= lpmli16
->Target
.wMid
;
1400 mliA
.Target
.wPid
= lpmli16
->Target
.wPid
;
1401 mliA
.Target
.vDriverVersion
= lpmli16
->Target
.vDriverVersion
;
1402 strcpy(mliA
.Target
.szPname
, lpmli16
->Target
.szPname
);
1405 FIXME("Unsupported fdwControls=0x%08lx\n", fdwInfo
);
1408 ret
= mixerGetLineInfoA(hmix
, &mliA
, fdwInfo
);
1410 lpmli16
->dwDestination
= mliA
.dwDestination
;
1411 lpmli16
->dwSource
= mliA
.dwSource
;
1412 lpmli16
->dwLineID
= mliA
.dwLineID
;
1413 lpmli16
->fdwLine
= mliA
.fdwLine
;
1414 lpmli16
->dwUser
= mliA
.dwUser
;
1415 lpmli16
->dwComponentType
= mliA
.dwComponentType
;
1416 lpmli16
->cChannels
= mliA
.cChannels
;
1417 lpmli16
->cConnections
= mliA
.cConnections
;
1418 lpmli16
->cControls
= mliA
.cControls
;
1419 strcpy(lpmli16
->szShortName
, mliA
.szShortName
);
1420 strcpy(lpmli16
->szName
, mliA
.szName
);
1421 lpmli16
->Target
.dwType
= mliA
.Target
.dwType
;
1422 lpmli16
->Target
.dwDeviceID
= mliA
.Target
.dwDeviceID
;
1423 lpmli16
->Target
.wMid
= mliA
.Target
.wMid
;
1424 lpmli16
->Target
.wPid
= mliA
.Target
.wPid
;
1425 lpmli16
->Target
.vDriverVersion
= mliA
.Target
.vDriverVersion
;
1426 strcpy(lpmli16
->Target
.szPname
, mliA
.Target
.szPname
);
1431 /**************************************************************************
1432 * mixerSetControlDetails [WINMM.@]
1434 UINT WINAPI
mixerSetControlDetails(HMIXEROBJ hmix
, LPMIXERCONTROLDETAILS lpmcdA
,
1439 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcdA
, fdwDetails
);
1441 if ((lpwm
= MIXER_GetDev(hmix
, fdwDetails
)) == NULL
)
1442 return MMSYSERR_INVALHANDLE
;
1444 return MMDRV_Message(&lpwm
->mld
, MXDM_SETCONTROLDETAILS
, (DWORD
)lpmcdA
,
1448 /**************************************************************************
1449 * mixerSetControlDetails [MMSYSTEM.809]
1451 UINT16 WINAPI
mixerSetControlDetails16(HMIXEROBJ16 hmix
,
1452 LPMIXERCONTROLDETAILS16 lpmcd
,
1455 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcd
, fdwDetails
);
1456 return MMSYSERR_NOTENABLED
;
1459 /**************************************************************************
1460 * mixerMessage [WINMM.@]
1462 UINT WINAPI
mixerMessage(HMIXER hmix
, UINT uMsg
, DWORD dwParam1
, DWORD dwParam2
)
1466 TRACE("(%04lx, %d, %08lx, %08lx): semi-stub?\n",
1467 (DWORD
)hmix
, uMsg
, dwParam1
, dwParam2
);
1469 if ((wmld
= MMDRV_Get(hmix
, MMDRV_MIXER
, FALSE
)) == NULL
)
1470 return MMSYSERR_INVALHANDLE
;
1472 return MMDRV_Message(wmld
, uMsg
, dwParam1
, dwParam2
, TRUE
);
1475 /**************************************************************************
1476 * mixerMessage [MMSYSTEM.804]
1478 DWORD WINAPI
mixerMessage16(HMIXER16 hmix
, UINT16 uMsg
, DWORD dwParam1
,
1481 return mixerMessage(hmix
, uMsg
, dwParam1
, dwParam2
);
1484 /**************************************************************************
1485 * auxGetNumDevs [WINMM.@]
1487 UINT WINAPI
auxGetNumDevs(void)
1489 return MMDRV_GetNum(MMDRV_AUX
);
1492 /**************************************************************************
1493 * auxGetNumDevs [MMSYSTEM.350]
1495 UINT16 WINAPI
auxGetNumDevs16(void)
1497 return MMDRV_GetNum(MMDRV_AUX
);
1500 /**************************************************************************
1501 * auxGetDevCapsW [WINMM.@]
1503 UINT WINAPI
auxGetDevCapsW(UINT uDeviceID
, LPAUXCAPSW lpCaps
, UINT uSize
)
1506 UINT ret
= auxGetDevCapsA(uDeviceID
, &acA
, sizeof(acA
));
1508 lpCaps
->wMid
= acA
.wMid
;
1509 lpCaps
->wPid
= acA
.wPid
;
1510 lpCaps
->vDriverVersion
= acA
.vDriverVersion
;
1511 MultiByteToWideChar( CP_ACP
, 0, acA
.szPname
, -1, lpCaps
->szPname
,
1512 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
1513 lpCaps
->wTechnology
= acA
.wTechnology
;
1514 lpCaps
->dwSupport
= acA
.dwSupport
;
1518 /**************************************************************************
1519 * auxGetDevCapsA [WINMM.@]
1521 UINT WINAPI
auxGetDevCapsA(UINT uDeviceID
, LPAUXCAPSA lpCaps
, UINT uSize
)
1525 TRACE("(%04X, %p, %d) !\n", uDeviceID
, lpCaps
, uSize
);
1527 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1528 return MMSYSERR_INVALHANDLE
;
1529 return MMDRV_Message(wmld
, AUXDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
1532 /**************************************************************************
1533 * auxGetDevCaps [MMSYSTEM.351]
1535 UINT16 WINAPI
auxGetDevCaps16(UINT16 uDeviceID
, LPAUXCAPS16 lpCaps
, UINT16 uSize
)
1539 TRACE("(%04X, %p, %d) !\n", uDeviceID
, lpCaps
, uSize
);
1541 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1542 return MMSYSERR_INVALHANDLE
;
1543 return MMDRV_Message(wmld
, AUXDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
1546 /**************************************************************************
1547 * auxGetVolume [WINMM.@]
1549 UINT WINAPI
auxGetVolume(UINT uDeviceID
, DWORD
* lpdwVolume
)
1553 TRACE("(%04X, %p) !\n", uDeviceID
, lpdwVolume
);
1555 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1556 return MMSYSERR_INVALHANDLE
;
1557 return MMDRV_Message(wmld
, AUXDM_GETVOLUME
, (DWORD
)lpdwVolume
, 0L, TRUE
);
1560 /**************************************************************************
1561 * auxGetVolume [MMSYSTEM.352]
1563 UINT16 WINAPI
auxGetVolume16(UINT16 uDeviceID
, LPDWORD lpdwVolume
)
1567 TRACE("(%04X, %p) !\n", uDeviceID
, lpdwVolume
);
1569 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1570 return MMSYSERR_INVALHANDLE
;
1571 return MMDRV_Message(wmld
, AUXDM_GETVOLUME
, (DWORD
)lpdwVolume
, 0L, TRUE
);
1574 /**************************************************************************
1575 * auxSetVolume [WINMM.@]
1577 UINT WINAPI
auxSetVolume(UINT uDeviceID
, DWORD dwVolume
)
1581 TRACE("(%04X, %lu) !\n", uDeviceID
, dwVolume
);
1583 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1584 return MMSYSERR_INVALHANDLE
;
1585 return MMDRV_Message(wmld
, AUXDM_SETVOLUME
, dwVolume
, 0L, TRUE
);
1588 /**************************************************************************
1589 * auxSetVolume [MMSYSTEM.353]
1591 UINT16 WINAPI
auxSetVolume16(UINT16 uDeviceID
, DWORD dwVolume
)
1595 TRACE("(%04X, %lu) !\n", uDeviceID
, dwVolume
);
1597 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1598 return MMSYSERR_INVALHANDLE
;
1599 return MMDRV_Message(wmld
, AUXDM_SETVOLUME
, dwVolume
, 0L, TRUE
);
1602 /**************************************************************************
1603 * auxOutMessage [WINMM.@]
1605 DWORD WINAPI
auxOutMessage(UINT uDeviceID
, UINT uMessage
, DWORD dw1
, DWORD dw2
)
1609 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1610 return MMSYSERR_INVALHANDLE
;
1612 return MMDRV_Message(wmld
, uMessage
, dw1
, dw2
, TRUE
);
1615 /**************************************************************************
1616 * auxOutMessage [MMSYSTEM.354]
1618 DWORD WINAPI
auxOutMessage16(UINT16 uDeviceID
, UINT16 uMessage
, DWORD dw1
, DWORD dw2
)
1622 TRACE("(%04X, %04X, %08lX, %08lX)\n", uDeviceID
, uMessage
, dw1
, dw2
);
1625 case AUXDM_GETNUMDEVS
:
1626 case AUXDM_SETVOLUME
:
1627 /* no argument conversion needed */
1629 case AUXDM_GETVOLUME
:
1630 return auxGetVolume16(uDeviceID
, MapSL(dw1
));
1631 case AUXDM_GETDEVCAPS
:
1632 return auxGetDevCaps16(uDeviceID
, MapSL(dw1
), dw2
);
1634 TRACE("(%04x, %04x, %08lx, %08lx): unhandled message\n",
1635 uDeviceID
, uMessage
, dw1
, dw2
);
1638 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1639 return MMSYSERR_INVALHANDLE
;
1641 return MMDRV_Message(wmld
, uMessage
, dw1
, dw2
, TRUE
);
1644 /**************************************************************************
1645 * mciGetErrorStringW [WINMM.@]
1647 BOOL WINAPI
mciGetErrorStringW(DWORD wError
, LPWSTR lpstrBuffer
, UINT uLength
)
1649 LPSTR bufstr
= HeapAlloc(GetProcessHeap(), 0, uLength
);
1650 BOOL ret
= mciGetErrorStringA(wError
, bufstr
, uLength
);
1652 MultiByteToWideChar( CP_ACP
, 0, bufstr
, -1, lpstrBuffer
, uLength
);
1653 HeapFree(GetProcessHeap(), 0, bufstr
);
1657 /**************************************************************************
1658 * mciGetErrorString [MMSYSTEM.706]
1660 BOOL16 WINAPI
mciGetErrorString16(DWORD wError
, LPSTR lpstrBuffer
, UINT16 uLength
)
1662 return mciGetErrorStringA(wError
, lpstrBuffer
, uLength
);
1665 /**************************************************************************
1666 * mciGetErrorStringA [WINMM.@]
1668 BOOL WINAPI
mciGetErrorStringA(DWORD dwError
, LPSTR lpstrBuffer
, UINT uLength
)
1672 if (lpstrBuffer
!= NULL
&& uLength
> 0 &&
1673 dwError
>= MCIERR_BASE
&& dwError
<= MCIERR_CUSTOM_DRIVER_BASE
) {
1675 if (LoadStringA(MULTIMEDIA_GetIData()->hWinMM32Instance
,
1676 dwError
, lpstrBuffer
, uLength
) > 0) {
1683 /**************************************************************************
1684 * mciDriverNotify [MMSYSTEM.711]
1686 BOOL16 WINAPI
mciDriverNotify16(HWND16 hWndCallBack
, UINT16 wDevID
, UINT16 wStatus
)
1688 TRACE("(%04X, %04x, %04X)\n", hWndCallBack
, wDevID
, wStatus
);
1690 return PostMessageA(hWndCallBack
, MM_MCINOTIFY
, wStatus
, wDevID
);
1693 /**************************************************************************
1694 * mciDriverNotify [WINMM.@]
1696 BOOL WINAPI
mciDriverNotify(HWND hWndCallBack
, UINT wDevID
, UINT wStatus
)
1699 TRACE("(%08X, %04x, %04X)\n", hWndCallBack
, wDevID
, wStatus
);
1701 return PostMessageA(hWndCallBack
, MM_MCINOTIFY
, wStatus
, wDevID
);
1704 /**************************************************************************
1705 * mciGetDriverData [MMSYSTEM.708]
1707 DWORD WINAPI
mciGetDriverData16(UINT16 uDeviceID
)
1709 return mciGetDriverData(uDeviceID
);
1712 /**************************************************************************
1713 * mciGetDriverData [WINMM.@]
1715 DWORD WINAPI
mciGetDriverData(UINT uDeviceID
)
1717 LPWINE_MCIDRIVER wmd
;
1719 TRACE("(%04x)\n", uDeviceID
);
1721 wmd
= MCI_GetDriver(uDeviceID
);
1724 WARN("Bad uDeviceID\n");
1728 return wmd
->dwPrivate
;
1731 /**************************************************************************
1732 * mciSetDriverData [MMSYSTEM.707]
1734 BOOL16 WINAPI
mciSetDriverData16(UINT16 uDeviceID
, DWORD data
)
1736 return mciSetDriverData(uDeviceID
, data
);
1739 /**************************************************************************
1740 * mciSetDriverData [WINMM.@]
1742 BOOL WINAPI
mciSetDriverData(UINT uDeviceID
, DWORD data
)
1744 LPWINE_MCIDRIVER wmd
;
1746 TRACE("(%04x, %08lx)\n", uDeviceID
, data
);
1748 wmd
= MCI_GetDriver(uDeviceID
);
1751 WARN("Bad uDeviceID\n");
1755 wmd
->dwPrivate
= data
;
1759 /**************************************************************************
1760 * mciSendCommandA [WINMM.@]
1762 DWORD WINAPI
mciSendCommandA(UINT wDevID
, UINT wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1766 TRACE("(%08x, %s, %08lx, %08lx)\n",
1767 wDevID
, MCI_MessageToString(wMsg
), dwParam1
, dwParam2
);
1769 dwRet
= MCI_SendCommand(wDevID
, wMsg
, dwParam1
, dwParam2
, TRUE
);
1770 dwRet
= MCI_CleanUp(dwRet
, wMsg
, dwParam2
, TRUE
);
1771 TRACE("=> %08lx\n", dwRet
);
1775 /**************************************************************************
1776 * mciSendCommandW [WINMM.@]
1778 DWORD WINAPI
mciSendCommandW(UINT wDevID
, UINT wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1780 FIXME("(%08x, %s, %08lx, %08lx): stub\n",
1781 wDevID
, MCI_MessageToString(wMsg
), dwParam1
, dwParam2
);
1782 return MCIERR_UNSUPPORTED_FUNCTION
;
1785 /**************************************************************************
1786 * mciSendCommand [MMSYSTEM.701]
1788 DWORD WINAPI
mciSendCommand16(UINT16 wDevID
, UINT16 wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1792 TRACE("(%04X, %s, %08lX, %08lX)\n",
1793 wDevID
, MCI_MessageToString(wMsg
), dwParam1
, dwParam2
);
1795 dwRet
= MCI_SendCommand(wDevID
, wMsg
, dwParam1
, dwParam2
, FALSE
);
1796 dwRet
= MCI_CleanUp(dwRet
, wMsg
, dwParam2
, FALSE
);
1797 TRACE("=> %ld\n", dwRet
);
1801 /**************************************************************************
1802 * mciGetDeviceID [MMSYSTEM.703]
1804 UINT16 WINAPI
mciGetDeviceID16(LPCSTR lpstrName
)
1806 TRACE("(\"%s\")\n", lpstrName
);
1808 return MCI_GetDriverFromString(lpstrName
);
1811 /**************************************************************************
1812 * mciGetDeviceIDA [WINMM.@]
1814 UINT WINAPI
mciGetDeviceIDA(LPCSTR lpstrName
)
1816 return MCI_GetDriverFromString(lpstrName
);
1819 /**************************************************************************
1820 * mciGetDeviceIDW [WINMM.@]
1822 UINT WINAPI
mciGetDeviceIDW(LPCWSTR lpwstrName
)
1827 lpstrName
= HEAP_strdupWtoA(GetProcessHeap(), 0, lpwstrName
);
1828 ret
= MCI_GetDriverFromString(lpstrName
);
1829 HeapFree(GetProcessHeap(), 0, lpstrName
);
1833 /**************************************************************************
1834 * MCI_DefYieldProc [internal]
1836 UINT WINAPI
MCI_DefYieldProc(MCIDEVICEID wDevID
, DWORD data
)
1840 TRACE("(0x%04x, 0x%08lx)\n", wDevID
, data
);
1842 if ((HIWORD(data
) != 0 && GetActiveWindow() != HIWORD(data
)) ||
1843 (GetAsyncKeyState(LOWORD(data
)) & 1) == 0) {
1849 msg
.hwnd
= HIWORD(data
);
1850 while (!PeekMessageA(&msg
, HIWORD(data
), WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
));
1856 /**************************************************************************
1857 * mciSetYieldProc [MMSYSTEM.714]
1859 BOOL16 WINAPI
mciSetYieldProc16(UINT16 uDeviceID
, YIELDPROC16 fpYieldProc
, DWORD dwYieldData
)
1861 LPWINE_MCIDRIVER wmd
;
1863 TRACE("(%u, %p, %08lx)\n", uDeviceID
, fpYieldProc
, dwYieldData
);
1865 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
1866 WARN("Bad uDeviceID\n");
1870 wmd
->lpfnYieldProc
= (YIELDPROC
)fpYieldProc
;
1871 wmd
->dwYieldData
= dwYieldData
;
1877 /**************************************************************************
1878 * mciSetYieldProc [WINMM.@]
1880 BOOL WINAPI
mciSetYieldProc(UINT uDeviceID
, YIELDPROC fpYieldProc
, DWORD dwYieldData
)
1882 LPWINE_MCIDRIVER wmd
;
1884 TRACE("(%u, %p, %08lx)\n", uDeviceID
, fpYieldProc
, dwYieldData
);
1886 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
1887 WARN("Bad uDeviceID\n");
1891 wmd
->lpfnYieldProc
= fpYieldProc
;
1892 wmd
->dwYieldData
= dwYieldData
;
1898 /**************************************************************************
1899 * mciGetDeviceIDFromElementID [MMSYSTEM.715]
1901 UINT16 WINAPI
mciGetDeviceIDFromElementID16(DWORD dwElementID
, LPCSTR lpstrType
)
1903 FIXME("(%lu, %s) stub\n", dwElementID
, lpstrType
);
1907 /**************************************************************************
1908 * mciGetDeviceIDFromElementIDW [WINMM.@]
1910 UINT WINAPI
mciGetDeviceIDFromElementIDW(DWORD dwElementID
, LPCWSTR lpstrType
)
1912 /* FIXME: that's rather strange, there is no
1913 * mciGetDeviceIDFromElementID32A in winmm.spec
1915 FIXME("(%lu, %p) stub\n", dwElementID
, lpstrType
);
1919 /**************************************************************************
1920 * mciGetYieldProc [MMSYSTEM.716]
1922 YIELDPROC16 WINAPI
mciGetYieldProc16(UINT16 uDeviceID
, DWORD
* lpdwYieldData
)
1924 LPWINE_MCIDRIVER wmd
;
1926 TRACE("(%u, %p)\n", uDeviceID
, lpdwYieldData
);
1928 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
1929 WARN("Bad uDeviceID\n");
1932 if (!wmd
->lpfnYieldProc
) {
1933 WARN("No proc set\n");
1937 WARN("Proc is 32 bit\n");
1940 return (YIELDPROC16
)wmd
->lpfnYieldProc
;
1943 /**************************************************************************
1944 * mciGetYieldProc [WINMM.@]
1946 YIELDPROC WINAPI
mciGetYieldProc(UINT uDeviceID
, DWORD
* lpdwYieldData
)
1948 LPWINE_MCIDRIVER wmd
;
1950 TRACE("(%u, %p)\n", uDeviceID
, lpdwYieldData
);
1952 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
1953 WARN("Bad uDeviceID\n");
1956 if (!wmd
->lpfnYieldProc
) {
1957 WARN("No proc set\n");
1961 WARN("Proc is 32 bit\n");
1964 return wmd
->lpfnYieldProc
;
1967 /**************************************************************************
1968 * mciGetCreatorTask [MMSYSTEM.717]
1970 HTASK16 WINAPI
mciGetCreatorTask16(UINT16 uDeviceID
)
1972 LPWINE_MCIDRIVER wmd
;
1975 if ((wmd
= MCI_GetDriver(uDeviceID
))) ret
= wmd
->hCreatorTask
;
1977 TRACE("(%u) => %04x\n", uDeviceID
, ret
);
1981 /**************************************************************************
1982 * mciGetCreatorTask [WINMM.@]
1984 HTASK WINAPI
mciGetCreatorTask(UINT uDeviceID
)
1986 LPWINE_MCIDRIVER wmd
;
1989 if ((wmd
= MCI_GetDriver(uDeviceID
))) ret
= (HTASK
)wmd
->CreatorThread
;
1991 TRACE("(%u) => %08x\n", uDeviceID
, ret
);
1995 /**************************************************************************
1996 * mciDriverYield [MMSYSTEM.710]
1998 UINT16 WINAPI
mciDriverYield16(UINT16 uDeviceID
)
2000 LPWINE_MCIDRIVER wmd
;
2003 /* TRACE("(%04x)\n", uDeviceID); */
2005 if (!(wmd
= MCI_GetDriver(uDeviceID
)) || !wmd
->lpfnYieldProc
|| wmd
->bIs32
) {
2008 ret
= wmd
->lpfnYieldProc(uDeviceID
, wmd
->dwYieldData
);
2014 /**************************************************************************
2015 * mciDriverYield [WINMM.@]
2017 UINT WINAPI
mciDriverYield(UINT uDeviceID
)
2019 LPWINE_MCIDRIVER wmd
;
2022 TRACE("(%04x)\n", uDeviceID
);
2024 if (!(wmd
= MCI_GetDriver(uDeviceID
)) || !wmd
->lpfnYieldProc
|| !wmd
->bIs32
) {
2027 ret
= wmd
->lpfnYieldProc(uDeviceID
, wmd
->dwYieldData
);
2033 /**************************************************************************
2034 * midiOutGetNumDevs [WINMM.@]
2036 UINT WINAPI
midiOutGetNumDevs(void)
2038 return MMDRV_GetNum(MMDRV_MIDIOUT
);
2041 /**************************************************************************
2042 * midiOutGetNumDevs [MMSYSTEM.201]
2044 UINT16 WINAPI
midiOutGetNumDevs16(void)
2046 return MMDRV_GetNum(MMDRV_MIDIOUT
);
2049 /**************************************************************************
2050 * midiOutGetDevCapsW [WINMM.@]
2052 UINT WINAPI
midiOutGetDevCapsW(UINT uDeviceID
, LPMIDIOUTCAPSW lpCaps
,
2058 ret
= midiOutGetDevCapsA(uDeviceID
, &mocA
, sizeof(mocA
));
2059 lpCaps
->wMid
= mocA
.wMid
;
2060 lpCaps
->wPid
= mocA
.wPid
;
2061 lpCaps
->vDriverVersion
= mocA
.vDriverVersion
;
2062 MultiByteToWideChar( CP_ACP
, 0, mocA
.szPname
, -1, lpCaps
->szPname
,
2063 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
2064 lpCaps
->wTechnology
= mocA
.wTechnology
;
2065 lpCaps
->wVoices
= mocA
.wVoices
;
2066 lpCaps
->wNotes
= mocA
.wNotes
;
2067 lpCaps
->wChannelMask
= mocA
.wChannelMask
;
2068 lpCaps
->dwSupport
= mocA
.dwSupport
;
2072 /**************************************************************************
2073 * midiOutGetDevCapsA [WINMM.@]
2075 UINT WINAPI
midiOutGetDevCapsA(UINT uDeviceID
, LPMIDIOUTCAPSA lpCaps
,
2080 TRACE("(%u, %p, %u);\n", uDeviceID
, lpCaps
, uSize
);
2082 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
2084 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_MIDIOUT
, TRUE
)) == NULL
)
2085 return MMSYSERR_INVALHANDLE
;
2087 return MMDRV_Message(wmld
, MODM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
2090 /**************************************************************************
2091 * midiOutGetDevCaps [MMSYSTEM.202]
2093 UINT16 WINAPI
midiOutGetDevCaps16(UINT16 uDeviceID
, LPMIDIOUTCAPS16 lpCaps
,
2099 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
2101 dwRet
= midiOutGetDevCapsA(uDeviceID
, &capsA
, sizeof(capsA
));
2102 if (dwRet
== MMSYSERR_NOERROR
) {
2103 lpCaps
->wMid
= capsA
.wMid
;
2104 lpCaps
->wPid
= capsA
.wPid
;
2105 lpCaps
->vDriverVersion
= capsA
.vDriverVersion
;
2106 strcpy(lpCaps
->szPname
, capsA
.szPname
);
2107 lpCaps
->wTechnology
= capsA
.wTechnology
;
2108 lpCaps
->wVoices
= capsA
.wVoices
;
2109 lpCaps
->wNotes
= capsA
.wNotes
;
2110 lpCaps
->wChannelMask
= capsA
.wChannelMask
;
2111 lpCaps
->dwSupport
= capsA
.dwSupport
;
2116 /**************************************************************************
2117 * MIDI_GetErrorText [internal]
2119 static UINT16
MIDI_GetErrorText(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
2121 UINT16 ret
= MMSYSERR_BADERRNUM
;
2123 if (lpText
== NULL
) {
2124 ret
= MMSYSERR_INVALPARAM
;
2125 } else if (uSize
== 0) {
2126 ret
= MMSYSERR_NOERROR
;
2128 /* test has been removed 'coz MMSYSERR_BASE is 0, and gcc did emit
2129 * a warning for the test was always true */
2130 (/*uError >= MMSYSERR_BASE && */ uError
<= MMSYSERR_LASTERROR
) ||
2131 (uError
>= MIDIERR_BASE
&& uError
<= MIDIERR_LASTERROR
)) {
2133 if (LoadStringA(MULTIMEDIA_GetIData()->hWinMM32Instance
,
2134 uError
, lpText
, uSize
) > 0) {
2135 ret
= MMSYSERR_NOERROR
;
2141 /**************************************************************************
2142 * midiOutGetErrorTextA [WINMM.@]
2144 UINT WINAPI
midiOutGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
2146 return MIDI_GetErrorText(uError
, lpText
, uSize
);
2149 /**************************************************************************
2150 * midiOutGetErrorTextW [WINMM.@]
2152 UINT WINAPI
midiOutGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
2154 LPSTR xstr
= HeapAlloc(GetProcessHeap(), 0, uSize
);
2157 ret
= MIDI_GetErrorText(uError
, xstr
, uSize
);
2158 MultiByteToWideChar( CP_ACP
, 0, xstr
, -1, lpText
, uSize
);
2159 HeapFree(GetProcessHeap(), 0, xstr
);
2163 /**************************************************************************
2164 * midiOutGetErrorText [MMSYSTEM.203]
2166 UINT16 WINAPI
midiOutGetErrorText16(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
2168 return MIDI_GetErrorText(uError
, lpText
, uSize
);
2171 /**************************************************************************
2172 * MIDI_OutAlloc [internal]
2174 static LPWINE_MIDI
MIDI_OutAlloc(HMIDIOUT
* lphMidiOut
, LPDWORD lpdwCallback
,
2175 LPDWORD lpdwInstance
, LPDWORD lpdwFlags
,
2176 DWORD cIDs
, MIDIOPENSTRMID
* lpIDs
, BOOL bFrom32
)
2182 size
= sizeof(WINE_MIDI
) + (cIDs
? (cIDs
-1) : 0) * sizeof(MIDIOPENSTRMID
);
2184 lpwm
= (LPWINE_MIDI
)MMDRV_Alloc(size
, MMDRV_MIDIOUT
, &hMidiOut
, lpdwFlags
,
2185 lpdwCallback
, lpdwInstance
, bFrom32
);
2187 if (lphMidiOut
!= NULL
)
2188 *lphMidiOut
= hMidiOut
;
2191 lpwm
->mod
.hMidi
= hMidiOut
;
2192 lpwm
->mod
.dwCallback
= *lpdwCallback
;
2193 lpwm
->mod
.dwInstance
= *lpdwInstance
;
2194 lpwm
->mod
.dnDevNode
= 0;
2195 lpwm
->mod
.cIds
= cIDs
;
2197 memcpy(&(lpwm
->mod
.rgIds
), lpIDs
, cIDs
* sizeof(MIDIOPENSTRMID
));
2202 UINT
MMSYSTEM_midiOutOpen(HMIDIOUT
* lphMidiOut
, UINT uDeviceID
, DWORD dwCallback
,
2203 DWORD dwInstance
, DWORD dwFlags
, BOOL bFrom32
)
2209 TRACE("(%p, %d, %08lX, %08lX, %08lX);\n",
2210 lphMidiOut
, uDeviceID
, dwCallback
, dwInstance
, dwFlags
);
2212 if (lphMidiOut
!= NULL
) *lphMidiOut
= 0;
2214 lpwm
= MIDI_OutAlloc(&hMidiOut
, &dwCallback
, &dwInstance
, &dwFlags
,
2218 return MMSYSERR_NOMEM
;
2220 lpwm
->mld
.uDeviceID
= uDeviceID
;
2222 dwRet
= MMDRV_Open((LPWINE_MLD
)lpwm
, MODM_OPEN
, (DWORD
)&lpwm
->mod
,
2225 if (dwRet
!= MMSYSERR_NOERROR
) {
2226 MMDRV_Free(hMidiOut
, (LPWINE_MLD
)lpwm
);
2230 if (lphMidiOut
) *lphMidiOut
= hMidiOut
;
2231 TRACE("=> %d hMidi=%04x\n", dwRet
, hMidiOut
);
2236 /**************************************************************************
2237 * midiOutOpen [WINMM.@]
2239 UINT WINAPI
midiOutOpen(HMIDIOUT
* lphMidiOut
, UINT uDeviceID
,
2240 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
2242 return MMSYSTEM_midiOutOpen(lphMidiOut
, uDeviceID
, dwCallback
,
2243 dwInstance
, dwFlags
, TRUE
);
2246 /**************************************************************************
2247 * midiOutOpen [MMSYSTEM.204]
2249 UINT16 WINAPI
midiOutOpen16(HMIDIOUT16
* lphMidiOut
, UINT16 uDeviceID
,
2250 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
2255 ret
= MMSYSTEM_midiOutOpen(&hmo
, uDeviceID
, dwCallback
, dwInstance
,
2258 if (lphMidiOut
!= NULL
) *lphMidiOut
= hmo
;
2262 /**************************************************************************
2263 * midiOutClose [WINMM.@]
2265 UINT WINAPI
midiOutClose(HMIDIOUT hMidiOut
)
2270 TRACE("(%04X)\n", hMidiOut
);
2272 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2273 return MMSYSERR_INVALHANDLE
;
2275 dwRet
= MMDRV_Close(wmld
, MODM_CLOSE
);
2276 MMDRV_Free(hMidiOut
, wmld
);
2281 /**************************************************************************
2282 * midiOutClose [MMSYSTEM.205]
2284 UINT16 WINAPI
midiOutClose16(HMIDIOUT16 hMidiOut
)
2286 return midiOutClose(hMidiOut
);
2289 /**************************************************************************
2290 * midiOutPrepareHeader [WINMM.@]
2292 UINT WINAPI
midiOutPrepareHeader(HMIDIOUT hMidiOut
,
2293 MIDIHDR
* lpMidiOutHdr
, UINT uSize
)
2297 TRACE("(%04X, %p, %d)\n", hMidiOut
, lpMidiOutHdr
, uSize
);
2299 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2300 return MMSYSERR_INVALHANDLE
;
2302 return MMDRV_Message(wmld
, MODM_PREPARE
, (DWORD
)lpMidiOutHdr
, uSize
, TRUE
);
2305 /**************************************************************************
2306 * midiOutPrepareHeader [MMSYSTEM.206]
2308 UINT16 WINAPI
midiOutPrepareHeader16(HMIDIOUT16 hMidiOut
, /* [in] */
2309 SEGPTR lpsegMidiOutHdr
, /* [???] */
2310 UINT16 uSize
) /* [in] */
2314 TRACE("(%04X, %08lx, %d)\n", hMidiOut
, lpsegMidiOutHdr
, uSize
);
2316 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2317 return MMSYSERR_INVALHANDLE
;
2319 return MMDRV_Message(wmld
, MODM_PREPARE
, lpsegMidiOutHdr
, uSize
, FALSE
);
2322 /**************************************************************************
2323 * midiOutUnprepareHeader [WINMM.@]
2325 UINT WINAPI
midiOutUnprepareHeader(HMIDIOUT hMidiOut
,
2326 MIDIHDR
* lpMidiOutHdr
, UINT uSize
)
2330 TRACE("(%04X, %p, %d)\n", hMidiOut
, lpMidiOutHdr
, uSize
);
2332 if (!(lpMidiOutHdr
->dwFlags
& MHDR_PREPARED
)) {
2333 return MMSYSERR_NOERROR
;
2336 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2337 return MMSYSERR_INVALHANDLE
;
2339 return MMDRV_Message(wmld
, MODM_UNPREPARE
, (DWORD
)lpMidiOutHdr
, uSize
, TRUE
);
2342 /**************************************************************************
2343 * midiOutUnprepareHeader [MMSYSTEM.207]
2345 UINT16 WINAPI
midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut
, /* [in] */
2346 SEGPTR lpsegMidiOutHdr
, /* [???] */
2347 UINT16 uSize
) /* [in] */
2350 LPMIDIHDR16 lpMidiOutHdr
= MapSL(lpsegMidiOutHdr
);
2352 TRACE("(%04X, %08lx, %d)\n", hMidiOut
, lpsegMidiOutHdr
, uSize
);
2354 if (!(lpMidiOutHdr
->dwFlags
& MHDR_PREPARED
)) {
2355 return MMSYSERR_NOERROR
;
2358 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2359 return MMSYSERR_INVALHANDLE
;
2361 return MMDRV_Message(wmld
, MODM_UNPREPARE
, (DWORD
)lpsegMidiOutHdr
, uSize
, FALSE
);
2364 /**************************************************************************
2365 * midiOutShortMsg [WINMM.@]
2367 UINT WINAPI
midiOutShortMsg(HMIDIOUT hMidiOut
, DWORD dwMsg
)
2371 TRACE("(%04X, %08lX)\n", hMidiOut
, dwMsg
);
2373 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2374 return MMSYSERR_INVALHANDLE
;
2376 return MMDRV_Message(wmld
, MODM_DATA
, dwMsg
, 0L, FALSE
);
2379 /**************************************************************************
2380 * midiOutShortMsg [MMSYSTEM.208]
2382 UINT16 WINAPI
midiOutShortMsg16(HMIDIOUT16 hMidiOut
, DWORD dwMsg
)
2384 return midiOutShortMsg(hMidiOut
, dwMsg
);
2387 /**************************************************************************
2388 * midiOutLongMsg [WINMM.@]
2390 UINT WINAPI
midiOutLongMsg(HMIDIOUT hMidiOut
,
2391 MIDIHDR
* lpMidiOutHdr
, UINT uSize
)
2395 TRACE("(%04X, %p, %d)\n", hMidiOut
, lpMidiOutHdr
, uSize
);
2397 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2398 return MMSYSERR_INVALHANDLE
;
2400 return MMDRV_Message(wmld
, MODM_LONGDATA
, (DWORD
)lpMidiOutHdr
, uSize
, TRUE
);
2403 /**************************************************************************
2404 * midiOutLongMsg [MMSYSTEM.209]
2406 UINT16 WINAPI
midiOutLongMsg16(HMIDIOUT16 hMidiOut
, /* [in] */
2407 LPMIDIHDR16 lpsegMidiOutHdr
, /* [???] NOTE: SEGPTR */
2408 UINT16 uSize
) /* [in] */
2412 TRACE("(%04X, %p, %d)\n", hMidiOut
, lpsegMidiOutHdr
, uSize
);
2414 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2415 return MMSYSERR_INVALHANDLE
;
2417 return MMDRV_Message(wmld
, MODM_LONGDATA
, (DWORD
)lpsegMidiOutHdr
, uSize
, FALSE
);
2420 /**************************************************************************
2421 * midiOutReset [WINMM.@]
2423 UINT WINAPI
midiOutReset(HMIDIOUT hMidiOut
)
2427 TRACE("(%04X)\n", hMidiOut
);
2429 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2430 return MMSYSERR_INVALHANDLE
;
2432 return MMDRV_Message(wmld
, MODM_RESET
, 0L, 0L, TRUE
);
2435 /**************************************************************************
2436 * midiOutReset [MMSYSTEM.210]
2438 UINT16 WINAPI
midiOutReset16(HMIDIOUT16 hMidiOut
)
2440 return midiOutReset(hMidiOut
);
2443 /**************************************************************************
2444 * midiOutGetVolume [WINMM.@]
2446 UINT WINAPI
midiOutGetVolume(UINT uDeviceID
, DWORD
* lpdwVolume
)
2450 TRACE("(%04X, %p);\n", uDeviceID
, lpdwVolume
);
2452 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_MIDIOUT
, TRUE
)) == NULL
)
2453 return MMSYSERR_INVALHANDLE
;
2455 return MMDRV_Message(wmld
, MODM_GETVOLUME
, (DWORD
)lpdwVolume
, 0L, TRUE
);
2458 /**************************************************************************
2459 * midiOutGetVolume [MMSYSTEM.211]
2461 UINT16 WINAPI
midiOutGetVolume16(UINT16 uDeviceID
, DWORD
* lpdwVolume
)
2463 return midiOutGetVolume(uDeviceID
, lpdwVolume
);
2466 /**************************************************************************
2467 * midiOutSetVolume [WINMM.@]
2469 UINT WINAPI
midiOutSetVolume(UINT uDeviceID
, DWORD dwVolume
)
2473 TRACE("(%04X, %ld);\n", uDeviceID
, dwVolume
);
2475 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_MIDIOUT
, TRUE
)) == NULL
)
2476 return MMSYSERR_INVALHANDLE
;
2478 return MMDRV_Message(wmld
, MODM_SETVOLUME
, dwVolume
, 0L, TRUE
);
2481 /**************************************************************************
2482 * midiOutSetVolume [MMSYSTEM.212]
2484 UINT16 WINAPI
midiOutSetVolume16(UINT16 uDeviceID
, DWORD dwVolume
)
2486 return midiOutSetVolume(uDeviceID
, dwVolume
);
2489 /**************************************************************************
2490 * midiOutCachePatches [WINMM.@]
2492 UINT WINAPI
midiOutCachePatches(HMIDIOUT hMidiOut
, UINT uBank
,
2493 WORD
* lpwPatchArray
, UINT uFlags
)
2495 /* not really necessary to support this */
2496 FIXME("not supported yet\n");
2497 return MMSYSERR_NOTSUPPORTED
;
2500 /**************************************************************************
2501 * midiOutCachePatches [MMSYSTEM.213]
2503 UINT16 WINAPI
midiOutCachePatches16(HMIDIOUT16 hMidiOut
, UINT16 uBank
,
2504 WORD
* lpwPatchArray
, UINT16 uFlags
)
2506 return midiOutCachePatches(hMidiOut
, uBank
, lpwPatchArray
, uFlags
);
2509 /**************************************************************************
2510 * midiOutCacheDrumPatches [WINMM.@]
2512 UINT WINAPI
midiOutCacheDrumPatches(HMIDIOUT hMidiOut
, UINT uPatch
,
2513 WORD
* lpwKeyArray
, UINT uFlags
)
2515 FIXME("not supported yet\n");
2516 return MMSYSERR_NOTSUPPORTED
;
2519 /**************************************************************************
2520 * midiOutCacheDrumPatches [MMSYSTEM.214]
2522 UINT16 WINAPI
midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut
, UINT16 uPatch
,
2523 WORD
* lpwKeyArray
, UINT16 uFlags
)
2525 return midiOutCacheDrumPatches16(hMidiOut
, uPatch
, lpwKeyArray
, uFlags
);
2528 /**************************************************************************
2529 * midiOutGetID [WINMM.@]
2531 UINT WINAPI
midiOutGetID(HMIDIOUT hMidiOut
, UINT
* lpuDeviceID
)
2535 TRACE("(%04X, %p)\n", hMidiOut
, lpuDeviceID
);
2537 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
2538 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2539 return MMSYSERR_INVALHANDLE
;
2541 *lpuDeviceID
= wmld
->uDeviceID
;
2542 return MMSYSERR_NOERROR
;
2545 /**************************************************************************
2546 * midiOutGetID [MMSYSTEM.215]
2548 UINT16 WINAPI
midiOutGetID16(HMIDIOUT16 hMidiOut
, UINT16
* lpuDeviceID
)
2552 TRACE("(%04X, %p)\n", hMidiOut
, lpuDeviceID
);
2554 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
2555 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2556 return MMSYSERR_INVALHANDLE
;
2558 *lpuDeviceID
= wmld
->uDeviceID
;
2559 return MMSYSERR_NOERROR
;
2562 /**************************************************************************
2563 * midiOutMessage [WINMM.@]
2565 DWORD WINAPI
midiOutMessage(HMIDIOUT hMidiOut
, UINT uMessage
,
2566 DWORD dwParam1
, DWORD dwParam2
)
2570 TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiOut
, uMessage
, dwParam1
, dwParam2
);
2572 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
) {
2574 if (uMessage
== 0x0001) {
2575 *(LPDWORD
)dwParam1
= 1;
2578 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, TRUE
)) != NULL
) {
2579 return MMDRV_PhysicalFeatures(wmld
, uMessage
, dwParam1
, dwParam2
);
2581 return MMSYSERR_INVALHANDLE
;
2587 FIXME("can't handle OPEN or CLOSE message!\n");
2588 return MMSYSERR_NOTSUPPORTED
;
2590 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
2593 /**************************************************************************
2594 * midiOutMessage [MMSYSTEM.216]
2596 DWORD WINAPI
midiOutMessage16(HMIDIOUT16 hMidiOut
, UINT16 uMessage
,
2597 DWORD dwParam1
, DWORD dwParam2
)
2601 TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiOut
, uMessage
, dwParam1
, dwParam2
);
2603 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2604 return MMSYSERR_INVALHANDLE
;
2609 FIXME("can't handle OPEN or CLOSE message!\n");
2610 return MMSYSERR_NOTSUPPORTED
;
2612 case MODM_GETVOLUME
:
2613 return midiOutGetVolume16(hMidiOut
, MapSL(dwParam1
));
2615 return midiOutLongMsg16(hMidiOut
, MapSL(dwParam1
), dwParam2
);
2617 /* lpMidiOutHdr is still a segmented pointer for this function */
2618 return midiOutPrepareHeader16(hMidiOut
, dwParam1
, dwParam2
);
2619 case MODM_UNPREPARE
:
2620 return midiOutUnprepareHeader16(hMidiOut
, dwParam1
, dwParam2
);
2622 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
2625 /**************************************************************************
2626 * midiInGetNumDevs [WINMM.@]
2628 UINT WINAPI
midiInGetNumDevs(void)
2630 return MMDRV_GetNum(MMDRV_MIDIIN
);
2633 /**************************************************************************
2634 * midiInGetNumDevs [MMSYSTEM.301]
2636 UINT16 WINAPI
midiInGetNumDevs16(void)
2638 return MMDRV_GetNum(MMDRV_MIDIIN
);
2641 /**************************************************************************
2642 * midiInGetDevCapsW [WINMM.@]
2644 UINT WINAPI
midiInGetDevCapsW(UINT uDeviceID
, LPMIDIINCAPSW lpCaps
, UINT uSize
)
2647 UINT ret
= midiInGetDevCapsA(uDeviceID
, &micA
, uSize
);
2649 if (ret
== MMSYSERR_NOERROR
) {
2650 lpCaps
->wMid
= micA
.wMid
;
2651 lpCaps
->wPid
= micA
.wPid
;
2652 lpCaps
->vDriverVersion
= micA
.vDriverVersion
;
2653 MultiByteToWideChar( CP_ACP
, 0, micA
.szPname
, -1, lpCaps
->szPname
,
2654 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
2655 lpCaps
->dwSupport
= micA
.dwSupport
;
2660 /**************************************************************************
2661 * midiInGetDevCapsA [WINMM.@]
2663 UINT WINAPI
midiInGetDevCapsA(UINT uDeviceID
, LPMIDIINCAPSA lpCaps
, UINT uSize
)
2667 TRACE("(%d, %p, %d);\n", uDeviceID
, lpCaps
, uSize
);
2669 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_MIDIIN
, TRUE
)) == NULL
)
2670 return MMSYSERR_INVALHANDLE
;
2672 return MMDRV_Message(wmld
, MIDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
2675 /**************************************************************************
2676 * midiInGetDevCaps [MMSYSTEM.302]
2678 UINT16 WINAPI
midiInGetDevCaps16(UINT16 uDeviceID
, LPMIDIINCAPS16 lpCaps
,
2682 UINT ret
= midiInGetDevCapsA(uDeviceID
, &micA
, uSize
);
2684 if (ret
== MMSYSERR_NOERROR
) {
2685 lpCaps
->wMid
= micA
.wMid
;
2686 lpCaps
->wPid
= micA
.wPid
;
2687 lpCaps
->vDriverVersion
= micA
.vDriverVersion
;
2688 strcpy(lpCaps
->szPname
, micA
.szPname
);
2689 lpCaps
->dwSupport
= micA
.dwSupport
;
2695 /**************************************************************************
2696 * midiInGetErrorTextW [WINMM.@]
2698 UINT WINAPI
midiInGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
2700 LPSTR xstr
= HeapAlloc(GetProcessHeap(), 0, uSize
);
2701 UINT ret
= MIDI_GetErrorText(uError
, xstr
, uSize
);
2703 MultiByteToWideChar( CP_ACP
, 0, xstr
, -1, lpText
, uSize
);
2704 HeapFree(GetProcessHeap(), 0, xstr
);
2708 /**************************************************************************
2709 * midiInGetErrorTextA [WINMM.@]
2711 UINT WINAPI
midiInGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
2713 return MIDI_GetErrorText(uError
, lpText
, uSize
);
2716 /**************************************************************************
2717 * midiInGetErrorText [MMSYSTEM.303]
2719 UINT16 WINAPI
midiInGetErrorText16(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
2721 return MIDI_GetErrorText(uError
, lpText
, uSize
);
2724 static UINT
MMSYSTEM_midiInOpen(HMIDIIN
* lphMidiIn
, UINT uDeviceID
, DWORD dwCallback
,
2725 DWORD dwInstance
, DWORD dwFlags
, BOOL bFrom32
)
2731 TRACE("(%p, %d, %08lX, %08lX, %08lX);\n",
2732 lphMidiIn
, uDeviceID
, dwCallback
, dwInstance
, dwFlags
);
2734 if (lphMidiIn
!= NULL
) *lphMidiIn
= 0;
2736 lpwm
= (LPWINE_MIDI
)MMDRV_Alloc(sizeof(WINE_MIDI
), MMDRV_MIDIIN
, &hMidiIn
,
2737 &dwFlags
, &dwCallback
, &dwInstance
, bFrom32
);
2740 return MMSYSERR_NOMEM
;
2742 lpwm
->mod
.hMidi
= hMidiIn
;
2743 lpwm
->mod
.dwCallback
= dwCallback
;
2744 lpwm
->mod
.dwInstance
= dwInstance
;
2746 lpwm
->mld
.uDeviceID
= uDeviceID
;
2747 dwRet
= MMDRV_Open(&lpwm
->mld
, MIDM_OPEN
, (DWORD
)&lpwm
->mod
, dwFlags
);
2749 if (dwRet
!= MMSYSERR_NOERROR
) {
2750 MMDRV_Free(hMidiIn
, &lpwm
->mld
);
2753 if (lphMidiIn
!= NULL
) *lphMidiIn
= hMidiIn
;
2754 TRACE("=> %ld hMidi=%04x\n", dwRet
, hMidiIn
);
2759 /**************************************************************************
2760 * midiInOpen [WINMM.@]
2762 UINT WINAPI
midiInOpen(HMIDIIN
* lphMidiIn
, UINT uDeviceID
,
2763 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
2765 return MMSYSTEM_midiInOpen(lphMidiIn
, uDeviceID
, dwCallback
,
2766 dwInstance
, dwFlags
, TRUE
);
2769 /**************************************************************************
2770 * midiInOpen [MMSYSTEM.304]
2772 UINT16 WINAPI
midiInOpen16(HMIDIIN16
* lphMidiIn
, UINT16 uDeviceID
,
2773 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
2778 ret
= MMSYSTEM_midiInOpen(&xhmid
, uDeviceID
, dwCallback
, dwInstance
,
2781 if (lphMidiIn
) *lphMidiIn
= xhmid
;
2785 /**************************************************************************
2786 * midiInClose [WINMM.@]
2788 UINT WINAPI
midiInClose(HMIDIIN hMidiIn
)
2793 TRACE("(%04X)\n", hMidiIn
);
2795 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2796 return MMSYSERR_INVALHANDLE
;
2798 dwRet
= MMDRV_Close(wmld
, MIDM_CLOSE
);
2799 MMDRV_Free(hMidiIn
, wmld
);
2803 /**************************************************************************
2804 * midiInClose [MMSYSTEM.305]
2806 UINT16 WINAPI
midiInClose16(HMIDIIN16 hMidiIn
)
2808 return midiInClose(hMidiIn
);
2811 /**************************************************************************
2812 * midiInPrepareHeader [WINMM.@]
2814 UINT WINAPI
midiInPrepareHeader(HMIDIIN hMidiIn
,
2815 MIDIHDR
* lpMidiInHdr
, UINT uSize
)
2819 TRACE("(%04X, %p, %d)\n", hMidiIn
, lpMidiInHdr
, uSize
);
2821 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2822 return MMSYSERR_INVALHANDLE
;
2824 return MMDRV_Message(wmld
, MIDM_PREPARE
, (DWORD
)lpMidiInHdr
, uSize
, TRUE
);
2827 /**************************************************************************
2828 * midiInPrepareHeader [MMSYSTEM.306]
2830 UINT16 WINAPI
midiInPrepareHeader16(HMIDIIN16 hMidiIn
, /* [in] */
2831 SEGPTR lpsegMidiInHdr
, /* [???] */
2832 UINT16 uSize
) /* [in] */
2836 TRACE("(%04X, %08lx, %d)\n", hMidiIn
, lpsegMidiInHdr
, uSize
);
2838 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2839 return MMSYSERR_INVALHANDLE
;
2841 return MMDRV_Message(wmld
, MIDM_PREPARE
, (DWORD
)lpsegMidiInHdr
, uSize
, FALSE
);
2844 /**************************************************************************
2845 * midiInUnprepareHeader [WINMM.@]
2847 UINT WINAPI
midiInUnprepareHeader(HMIDIIN hMidiIn
,
2848 MIDIHDR
* lpMidiInHdr
, UINT uSize
)
2852 TRACE("(%04X, %p, %d)\n", hMidiIn
, lpMidiInHdr
, uSize
);
2854 if (!(lpMidiInHdr
->dwFlags
& MHDR_PREPARED
)) {
2855 return MMSYSERR_NOERROR
;
2858 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2859 return MMSYSERR_INVALHANDLE
;
2861 return MMDRV_Message(wmld
, MIDM_UNPREPARE
, (DWORD
)lpMidiInHdr
, uSize
, TRUE
);
2864 /**************************************************************************
2865 * midiInUnprepareHeader [MMSYSTEM.307]
2867 UINT16 WINAPI
midiInUnprepareHeader16(HMIDIIN16 hMidiIn
, /* [in] */
2868 SEGPTR lpsegMidiInHdr
, /* [???] */
2869 UINT16 uSize
) /* [in] */
2872 LPMIDIHDR16 lpMidiInHdr
= MapSL(lpsegMidiInHdr
);
2874 TRACE("(%04X, %08lx, %d)\n", hMidiIn
, lpsegMidiInHdr
, uSize
);
2876 if (!(lpMidiInHdr
->dwFlags
& MHDR_PREPARED
)) {
2877 return MMSYSERR_NOERROR
;
2880 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2881 return MMSYSERR_INVALHANDLE
;
2883 return MMDRV_Message(wmld
, MIDM_UNPREPARE
, (DWORD
)lpsegMidiInHdr
, uSize
, FALSE
);
2886 /**************************************************************************
2887 * midiInAddBuffer [WINMM.@]
2889 UINT WINAPI
midiInAddBuffer(HMIDIIN hMidiIn
,
2890 MIDIHDR
* lpMidiInHdr
, UINT uSize
)
2894 TRACE("(%04X, %p, %d)\n", hMidiIn
, lpMidiInHdr
, uSize
);
2896 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2897 return MMSYSERR_INVALHANDLE
;
2899 return MMDRV_Message(wmld
, MIDM_ADDBUFFER
, (DWORD
)lpMidiInHdr
, uSize
, TRUE
);
2902 /**************************************************************************
2903 * midiInAddBuffer [MMSYSTEM.308]
2905 UINT16 WINAPI
midiInAddBuffer16(HMIDIIN16 hMidiIn
, /* [in] */
2906 MIDIHDR16
* lpsegMidiInHdr
, /* [???] NOTE: SEGPTR */
2907 UINT16 uSize
) /* [in] */
2911 TRACE("(%04X, %p, %d)\n", hMidiIn
, lpsegMidiInHdr
, uSize
);
2913 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2914 return MMSYSERR_INVALHANDLE
;
2916 return MMDRV_Message(wmld
, MIDM_ADDBUFFER
, (DWORD
)lpsegMidiInHdr
, uSize
, FALSE
);
2919 /**************************************************************************
2920 * midiInStart [WINMM.@]
2922 UINT WINAPI
midiInStart(HMIDIIN hMidiIn
)
2926 TRACE("(%04X)\n", hMidiIn
);
2928 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2929 return MMSYSERR_INVALHANDLE
;
2931 return MMDRV_Message(wmld
, MIDM_START
, 0L, 0L, TRUE
);
2934 /**************************************************************************
2935 * midiInStart [MMSYSTEM.309]
2937 UINT16 WINAPI
midiInStart16(HMIDIIN16 hMidiIn
)
2939 return midiInStart(hMidiIn
);
2942 /**************************************************************************
2943 * midiInStop [WINMM.@]
2945 UINT WINAPI
midiInStop(HMIDIIN hMidiIn
)
2949 TRACE("(%04X)\n", hMidiIn
);
2951 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2952 return MMSYSERR_INVALHANDLE
;
2954 return MMDRV_Message(wmld
, MIDM_STOP
, 0L, 0L, TRUE
);
2957 /**************************************************************************
2958 * midiInStop [MMSYSTEM.310]
2960 UINT16 WINAPI
midiInStop16(HMIDIIN16 hMidiIn
)
2962 return midiInStop(hMidiIn
);
2965 /**************************************************************************
2966 * midiInReset [WINMM.@]
2968 UINT WINAPI
midiInReset(HMIDIIN hMidiIn
)
2972 TRACE("(%04X)\n", hMidiIn
);
2974 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2975 return MMSYSERR_INVALHANDLE
;
2977 return MMDRV_Message(wmld
, MIDM_RESET
, 0L, 0L, TRUE
);
2980 /**************************************************************************
2981 * midiInReset [MMSYSTEM.311]
2983 UINT16 WINAPI
midiInReset16(HMIDIIN16 hMidiIn
)
2985 return midiInReset(hMidiIn
);
2988 /**************************************************************************
2989 * midiInGetID [WINMM.@]
2991 UINT WINAPI
midiInGetID(HMIDIIN hMidiIn
, UINT
* lpuDeviceID
)
2995 TRACE("(%04X, %p)\n", hMidiIn
, lpuDeviceID
);
2997 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
2999 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, TRUE
)) == NULL
)
3000 return MMSYSERR_INVALHANDLE
;
3002 *lpuDeviceID
= wmld
->uDeviceID
;
3004 return MMSYSERR_NOERROR
;
3007 /**************************************************************************
3008 * midiInGetID [MMSYSTEM.312]
3010 UINT16 WINAPI
midiInGetID16(HMIDIIN16 hMidiIn
, UINT16
* lpuDeviceID
)
3014 TRACE("(%04X, %p)\n", hMidiIn
, lpuDeviceID
);
3016 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
3018 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, TRUE
)) == NULL
)
3019 return MMSYSERR_INVALHANDLE
;
3021 *lpuDeviceID
= wmld
->uDeviceID
;
3023 return MMSYSERR_NOERROR
;
3026 /**************************************************************************
3027 * midiInMessage [WINMM.@]
3029 DWORD WINAPI
midiInMessage(HMIDIIN hMidiIn
, UINT uMessage
,
3030 DWORD dwParam1
, DWORD dwParam2
)
3034 TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiIn
, uMessage
, dwParam1
, dwParam2
);
3036 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
3037 return MMSYSERR_INVALHANDLE
;
3042 FIXME("can't handle OPEN or CLOSE message!\n");
3043 return MMSYSERR_NOTSUPPORTED
;
3045 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
3048 /**************************************************************************
3049 * midiInMessage [MMSYSTEM.313]
3051 DWORD WINAPI
midiInMessage16(HMIDIIN16 hMidiIn
, UINT16 uMessage
,
3052 DWORD dwParam1
, DWORD dwParam2
)
3056 TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiIn
, uMessage
, dwParam1
, dwParam2
);
3061 FIXME("can't handle OPEN or CLOSE message!\n");
3062 return MMSYSERR_NOTSUPPORTED
;
3064 case MIDM_GETDEVCAPS
:
3065 return midiInGetDevCaps16(hMidiIn
, MapSL(dwParam1
), dwParam2
);
3067 return midiInPrepareHeader16(hMidiIn
, dwParam1
, dwParam2
);
3068 case MIDM_UNPREPARE
:
3069 return midiInUnprepareHeader16(hMidiIn
, dwParam1
, dwParam2
);
3070 case MIDM_ADDBUFFER
:
3071 return midiInAddBuffer16(hMidiIn
, MapSL(dwParam1
), dwParam2
);
3074 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
3075 return MMSYSERR_INVALHANDLE
;
3077 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, FALSE
);
3080 typedef struct WINE_MIDIStream
{
3091 LPMIDIHDR lpMidiHdr
;
3094 #define WINE_MSM_HEADER (WM_USER+0)
3095 #define WINE_MSM_STOP (WM_USER+1)
3097 /**************************************************************************
3098 * MMSYSTEM_GetMidiStream [internal]
3100 static BOOL
MMSYSTEM_GetMidiStream(HMIDISTRM hMidiStrm
, WINE_MIDIStream
** lpMidiStrm
, WINE_MIDI
** lplpwm
)
3102 WINE_MIDI
* lpwm
= (LPWINE_MIDI
)MMDRV_Get(hMidiStrm
, MMDRV_MIDIOUT
, FALSE
);
3111 *lpMidiStrm
= (WINE_MIDIStream
*)lpwm
->mod
.rgIds
.dwStreamID
;
3113 return *lpMidiStrm
!= NULL
;
3116 /**************************************************************************
3117 * MMSYSTEM_MidiStream_Convert [internal]
3119 static DWORD
MMSYSTEM_MidiStream_Convert(WINE_MIDIStream
* lpMidiStrm
, DWORD pulse
)
3123 if (lpMidiStrm
->dwTimeDiv
== 0) {
3124 FIXME("Shouldn't happen. lpMidiStrm->dwTimeDiv = 0\n");
3125 } else if (lpMidiStrm
->dwTimeDiv
> 0x8000) { /* SMPTE, unchecked FIXME? */
3126 int nf
= -(char)HIBYTE(lpMidiStrm
->dwTimeDiv
); /* number of frames */
3127 int nsf
= LOBYTE(lpMidiStrm
->dwTimeDiv
); /* number of sub-frames */
3128 ret
= (pulse
* 1000) / (nf
* nsf
);
3130 ret
= (DWORD
)((double)pulse
* ((double)lpMidiStrm
->dwTempo
/ 1000) /
3131 (double)lpMidiStrm
->dwTimeDiv
);
3137 /**************************************************************************
3138 * MMSYSTEM_MidiStream_MessageHandler [internal]
3140 static BOOL
MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream
* lpMidiStrm
, LPWINE_MIDI lpwm
, LPMSG msg
)
3142 LPMIDIHDR lpMidiHdr
;
3146 switch (msg
->message
) {
3148 SetEvent(lpMidiStrm
->hEvent
);
3152 /* this is not quite what MS doc says... */
3153 midiOutReset(lpMidiStrm
->hDevice
);
3154 /* empty list of already submitted buffers */
3155 for (lpMidiHdr
= lpMidiStrm
->lpMidiHdr
; lpMidiHdr
; lpMidiHdr
= (LPMIDIHDR
)lpMidiHdr
->lpNext
) {
3156 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
3157 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
3159 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
, lpMidiStrm
->hDevice
,
3160 MM_MOM_DONE
, lpwm
->mod
.dwInstance
, (DWORD
)lpMidiHdr
, 0L);
3162 lpMidiStrm
->lpMidiHdr
= 0;
3163 SetEvent(lpMidiStrm
->hEvent
);
3165 case WINE_MSM_HEADER
:
3166 /* sets initial tick count for first MIDIHDR */
3167 if (!lpMidiStrm
->dwStartTicks
)
3168 lpMidiStrm
->dwStartTicks
= GetTickCount();
3170 /* FIXME(EPP): "I don't understand the content of the first MIDIHDR sent
3171 * by native mcimidi, it doesn't look like a correct one".
3172 * this trick allows to throw it away... but I don't like it.
3173 * It looks like part of the file I'm trying to play and definitively looks
3174 * like raw midi content
3175 * I'd really like to understand why native mcimidi sends it. Perhaps a bad
3176 * synchronization issue where native mcimidi is still processing raw MIDI
3177 * content before generating MIDIEVENTs ?
3179 * 4c 04 89 3b 00 81 7c 99 3b 43 00 99 23 5e 04 89 L..;..|.;C..#^..
3180 * 3b 00 00 89 23 00 7c 99 3b 45 00 99 28 62 04 89 ;...#.|.;E..(b..
3181 * 3b 00 00 89 28 00 81 7c 99 3b 4e 00 99 23 5e 04 ;...(..|.;N..#^.
3182 * 89 3b 00 00 89 23 00 7c 99 3b 45 00 99 23 78 04 .;...#.|.;E..#x.
3183 * 89 3b 00 00 89 23 00 81 7c 99 3b 48 00 99 23 5e .;...#..|.;H..#^
3184 * 04 89 3b 00 00 89 23 00 7c 99 3b 4e 00 99 28 62 ..;...#.|.;N..(b
3185 * 04 89 3b 00 00 89 28 00 81 7c 99 39 4c 00 99 23 ..;...(..|.9L..#
3186 * 5e 04 89 39 00 00 89 23 00 82 7c 99 3b 4c 00 99 ^..9...#..|.;L..
3187 * 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b 48 00 99 #^..;...#.|.;H..
3188 * 28 62 04 89 3b 00 00 89 28 00 81 7c 99 3b 3f 04 (b..;...(..|.;?.
3189 * 89 3b 00 1c 99 23 5e 04 89 23 00 5c 99 3b 45 00 .;...#^..#.\.;E.
3190 * 99 23 78 04 89 3b 00 00 89 23 00 81 7c 99 3b 46 .#x..;...#..|.;F
3191 * 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b 48 ..#^..;...#.|.;H
3192 * 00 99 28 62 04 89 3b 00 00 89 28 00 81 7c 99 3b ..(b..;...(..|.;
3193 * 46 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b F..#^..;...#.|.;
3194 * 48 00 99 23 78 04 89 3b 00 00 89 23 00 81 7c 99 H..#x..;...#..|.
3195 * 3b 4c 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 ;L..#^..;...#.|.
3197 lpMidiHdr
= (LPMIDIHDR
)msg
->lParam
;
3198 lpData
= lpMidiHdr
->lpData
;
3199 TRACE("Adding %s lpMidiHdr=%p [lpData=0x%08lx dwBufferLength=%lu/%lu dwFlags=0x%08lx size=%u]\n",
3200 (lpMidiHdr
->dwFlags
& MHDR_ISSTRM
) ? "stream" : "regular", lpMidiHdr
,
3201 (DWORD
)lpMidiHdr
, lpMidiHdr
->dwBufferLength
, lpMidiHdr
->dwBytesRecorded
,
3202 lpMidiHdr
->dwFlags
, msg
->wParam
);
3204 /* dumps content of lpMidiHdr->lpData
3205 * FIXME: there should be a debug routine somewhere that already does this
3206 * I hate spreading this type of shit all around the code
3208 for (dwToGo
= 0; dwToGo
< lpMidiHdr
->dwBufferLength
; dwToGo
+= 16) {
3212 for (i
= 0; i
< min(16, lpMidiHdr
->dwBufferLength
- dwToGo
); i
++)
3213 printf("%02x ", lpData
[dwToGo
+ i
]);
3216 for (i
= 0; i
< min(16, lpMidiHdr
->dwBufferLength
- dwToGo
); i
++) {
3217 ch
= lpData
[dwToGo
+ i
];
3218 printf("%c", (ch
>= 0x20 && ch
<= 0x7F) ? ch
: '.');
3223 if (((LPMIDIEVENT
)lpData
)->dwStreamID
!= 0 &&
3224 ((LPMIDIEVENT
)lpData
)->dwStreamID
!= 0xFFFFFFFF &&
3225 ((LPMIDIEVENT
)lpData
)->dwStreamID
!= (DWORD
)lpMidiStrm
) {
3226 FIXME("Dropping bad %s lpMidiHdr (streamID=%08lx)\n",
3227 (lpMidiHdr
->dwFlags
& MHDR_ISSTRM
) ? "stream" : "regular",
3228 ((LPMIDIEVENT
)lpData
)->dwStreamID
);
3229 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
3230 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
3232 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
, lpMidiStrm
->hDevice
,
3233 MM_MOM_DONE
, lpwm
->mod
.dwInstance
, (DWORD
)lpMidiHdr
, 0L);
3237 for (lpmh
= &lpMidiStrm
->lpMidiHdr
; *lpmh
; lpmh
= (LPMIDIHDR
*)&((*lpmh
)->lpNext
));
3239 lpMidiHdr
= (LPMIDIHDR
)msg
->lParam
;
3240 lpMidiHdr
->lpNext
= 0;
3241 lpMidiHdr
->dwFlags
|= MHDR_INQUEUE
;
3242 lpMidiHdr
->dwFlags
&= MHDR_DONE
;
3243 lpMidiHdr
->dwOffset
= 0;
3247 FIXME("Unknown message %d\n", msg
->message
);
3253 /**************************************************************************
3254 * MMSYSTEM_MidiStream_Player [internal]
3256 static DWORD CALLBACK
MMSYSTEM_MidiStream_Player(LPVOID pmt
)
3258 WINE_MIDIStream
* lpMidiStrm
= pmt
;
3263 LPMIDIHDR lpMidiHdr
;
3267 TRACE("(%p)!\n", lpMidiStrm
);
3270 (lpwm
= (LPWINE_MIDI
)MMDRV_Get(lpMidiStrm
->hDevice
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
3273 /* force thread's queue creation */
3274 /* Used to be InitThreadInput16(0, 5); */
3275 /* but following works also with hack in midiStreamOpen */
3276 PeekMessageA(&msg
, 0, 0, 0, 0);
3278 /* FIXME: this next line must be called before midiStreamOut or midiStreamRestart are called */
3279 SetEvent(lpMidiStrm
->hEvent
);
3280 TRACE("Ready to go 1\n");
3281 /* thread is started in paused mode */
3282 SuspendThread(lpMidiStrm
->hThread
);
3283 TRACE("Ready to go 2\n");
3285 lpMidiStrm
->dwStartTicks
= 0;
3286 lpMidiStrm
->dwPulses
= 0;
3288 lpMidiStrm
->lpMidiHdr
= 0;
3291 lpMidiHdr
= lpMidiStrm
->lpMidiHdr
;
3293 /* for first message, block until one arrives, then process all that are available */
3294 GetMessageA(&msg
, 0, 0, 0);
3296 if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm
, lpwm
, &msg
))
3298 } while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
));
3304 lpData
= lpMidiHdr
->lpData
;
3306 me
= (LPMIDIEVENT
)(lpData
+ lpMidiHdr
->dwOffset
);
3308 /* do we have to wait ? */
3309 if (me
->dwDeltaTime
) {
3310 lpMidiStrm
->dwPositionMS
+= MMSYSTEM_MidiStream_Convert(lpMidiStrm
, me
->dwDeltaTime
);
3311 lpMidiStrm
->dwPulses
+= me
->dwDeltaTime
;
3313 dwToGo
= lpMidiStrm
->dwStartTicks
+ lpMidiStrm
->dwPositionMS
;
3315 TRACE("%ld/%ld/%ld\n", dwToGo
, GetTickCount(), me
->dwDeltaTime
);
3316 while ((dwCurrTC
= GetTickCount()) < dwToGo
) {
3317 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, dwToGo
- dwCurrTC
, QS_ALLINPUT
) == WAIT_OBJECT_0
) {
3318 /* got a message, handle it */
3319 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) {
3320 if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm
, lpwm
, &msg
))
3325 /* timeout, so me->dwDeltaTime is elapsed, can break the while loop */
3330 switch (MEVT_EVENTTYPE(me
->dwEvent
& ~MEVT_F_CALLBACK
)) {
3332 FIXME("NIY: MEVT_COMMENT\n");
3333 /* do nothing, skip bytes */
3336 FIXME("NIY: MEVT_LONGMSG, aka sending Sysex event\n");
3341 midiOutShortMsg(lpMidiStrm
->hDevice
, MEVT_EVENTPARM(me
->dwEvent
));
3344 lpMidiStrm
->dwTempo
= MEVT_EVENTPARM(me
->dwEvent
);
3349 FIXME("Unknown MEVT (0x%02x)\n", MEVT_EVENTTYPE(me
->dwEvent
& ~MEVT_F_CALLBACK
));
3352 if (me
->dwEvent
& MEVT_F_CALLBACK
) {
3353 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
, lpMidiStrm
->hDevice
,
3354 MM_MOM_POSITIONCB
, lpwm
->mod
.dwInstance
, (LPARAM
)lpMidiHdr
, 0L);
3356 lpMidiHdr
->dwOffset
+= sizeof(MIDIEVENT
) - sizeof(me
->dwParms
);
3357 if (me
->dwEvent
& MEVT_F_LONG
)
3358 lpMidiHdr
->dwOffset
+= (MEVT_EVENTPARM(me
->dwEvent
) + 3) & ~3;
3359 if (lpMidiHdr
->dwOffset
>= lpMidiHdr
->dwBufferLength
) {
3360 /* done with this header */
3361 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
3362 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
3364 lpMidiStrm
->lpMidiHdr
= (LPMIDIHDR
)lpMidiHdr
->lpNext
;
3365 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
, lpMidiStrm
->hDevice
,
3366 MM_MOM_DONE
, lpwm
->mod
.dwInstance
, (DWORD
)lpMidiHdr
, 0L);
3371 TRACE("End of thread\n");
3373 return 0; /* for removing the warning, never executed */
3376 /**************************************************************************
3377 * MMSYSTEM_MidiStream_PostMessage [internal]
3379 static BOOL
MMSYSTEM_MidiStream_PostMessage(WINE_MIDIStream
* lpMidiStrm
, WORD msg
, DWORD pmt1
, DWORD pmt2
)
3381 if (PostThreadMessageA(lpMidiStrm
->dwThreadID
, msg
, pmt1
, pmt2
)) {
3384 ReleaseThunkLock(&count
);
3385 WaitForSingleObject(lpMidiStrm
->hEvent
, INFINITE
);
3386 RestoreThunkLock(count
);
3388 WARN("bad PostThreadMessageA\n");
3394 /**************************************************************************
3395 * midiStreamClose [WINMM.@]
3397 MMRESULT WINAPI
midiStreamClose(HMIDISTRM hMidiStrm
)
3399 WINE_MIDIStream
* lpMidiStrm
;
3401 TRACE("(%08x)!\n", hMidiStrm
);
3403 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
))
3404 return MMSYSERR_INVALHANDLE
;
3406 midiStreamStop(hMidiStrm
);
3407 MMSYSTEM_MidiStream_PostMessage(lpMidiStrm
, WM_QUIT
, 0, 0);
3408 HeapFree(GetProcessHeap(), 0, lpMidiStrm
);
3409 CloseHandle(lpMidiStrm
->hEvent
);
3411 return midiOutClose(hMidiStrm
);
3414 /**************************************************************************
3415 * MMSYSTEM_MidiStream_Open [internal]
3417 static MMRESULT WINAPI
MMSYSTEM_MidiStream_Open(HMIDISTRM
* lphMidiStrm
, LPUINT lpuDeviceID
,
3418 DWORD cMidi
, DWORD dwCallback
,
3419 DWORD dwInstance
, DWORD fdwOpen
, BOOL bFrom32
)
3421 WINE_MIDIStream
* lpMidiStrm
;
3423 MIDIOPENSTRMID mosm
;
3427 TRACE("(%p, %p, %ld, 0x%08lx, 0x%08lx, 0x%08lx)!\n",
3428 lphMidiStrm
, lpuDeviceID
, cMidi
, dwCallback
, dwInstance
, fdwOpen
);
3430 if (cMidi
!= 1 || lphMidiStrm
== NULL
|| lpuDeviceID
== NULL
)
3431 return MMSYSERR_INVALPARAM
;
3433 lpMidiStrm
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_MIDIStream
));
3435 return MMSYSERR_NOMEM
;
3437 lpMidiStrm
->dwTempo
= 500000;
3438 lpMidiStrm
->dwTimeDiv
= 480; /* 480 is 120 quater notes per minute *//* FIXME ??*/
3439 lpMidiStrm
->dwPositionMS
= 0;
3441 mosm
.dwStreamID
= (DWORD
)lpMidiStrm
;
3442 /* FIXME: the correct value is not allocated yet for MAPPER */
3443 mosm
.wDeviceID
= *lpuDeviceID
;
3444 lpwm
= MIDI_OutAlloc(&hMidiOut
, &dwCallback
, &dwInstance
, &fdwOpen
, 1, &mosm
, bFrom32
);
3445 lpMidiStrm
->hDevice
= hMidiOut
;
3447 *lphMidiStrm
= hMidiOut
;
3449 /* FIXME: is lpuDevice initialized upon entering midiStreamOpen ? */
3450 FIXME("*lpuDeviceID=%x\n", *lpuDeviceID
);
3451 lpwm
->mld
.uDeviceID
= *lpuDeviceID
= 0;
3453 ret
= MMDRV_Open(&lpwm
->mld
, MODM_OPEN
, (DWORD
)&lpwm
->mod
, fdwOpen
);
3454 lpMidiStrm
->hEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3455 lpMidiStrm
->wFlags
= HIWORD(fdwOpen
);
3457 lpMidiStrm
->hThread
= CreateThread(NULL
, 0, MMSYSTEM_MidiStream_Player
,
3458 lpMidiStrm
, 0, &(lpMidiStrm
->dwThreadID
));
3460 if (!lpMidiStrm
->hThread
) {
3461 midiStreamClose((HMIDISTRM
)hMidiOut
);
3462 return MMSYSERR_NOMEM
;
3465 /* wait for thread to have started, and for its queue to be created */
3469 /* (Release|Restore)ThunkLock() is needed when this method is called from 16 bit code,
3470 * (meaning the Win16Lock is set), so that it's released and the 32 bit thread running
3471 * MMSYSTEM_MidiStreamPlayer can acquire Win16Lock to create its queue.
3473 ReleaseThunkLock(&count
);
3474 WaitForSingleObject(lpMidiStrm
->hEvent
, INFINITE
);
3475 RestoreThunkLock(count
);
3478 TRACE("=> (%u/%d) hMidi=0x%04x ret=%d lpMidiStrm=%p\n",
3479 *lpuDeviceID
, lpwm
->mld
.uDeviceID
, *lphMidiStrm
, ret
, lpMidiStrm
);
3483 /**************************************************************************
3484 * midiStreamOpen [WINMM.@]
3486 MMRESULT WINAPI
midiStreamOpen(HMIDISTRM
* lphMidiStrm
, LPUINT lpuDeviceID
,
3487 DWORD cMidi
, DWORD dwCallback
,
3488 DWORD dwInstance
, DWORD fdwOpen
)
3490 return MMSYSTEM_MidiStream_Open(lphMidiStrm
, lpuDeviceID
, cMidi
, dwCallback
,
3491 dwInstance
, fdwOpen
, TRUE
);
3494 /**************************************************************************
3495 * midiStreamOut [WINMM.@]
3497 MMRESULT WINAPI
midiStreamOut(HMIDISTRM hMidiStrm
, LPMIDIHDR lpMidiHdr
,
3500 WINE_MIDIStream
* lpMidiStrm
;
3501 DWORD ret
= MMSYSERR_NOERROR
;
3503 TRACE("(%08x, %p, %u)!\n", hMidiStrm
, lpMidiHdr
, cbMidiHdr
);
3505 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3506 ret
= MMSYSERR_INVALHANDLE
;
3507 } else if (!lpMidiHdr
) {
3508 ret
= MMSYSERR_INVALPARAM
;
3510 if (!PostThreadMessageA(lpMidiStrm
->dwThreadID
,
3511 WINE_MSM_HEADER
, cbMidiHdr
,
3512 (DWORD
)lpMidiHdr
)) {
3513 WARN("bad PostThreadMessageA\n");
3514 ret
= MMSYSERR_ERROR
;
3520 /**************************************************************************
3521 * midiStreamPause [WINMM.@]
3523 MMRESULT WINAPI
midiStreamPause(HMIDISTRM hMidiStrm
)
3525 WINE_MIDIStream
* lpMidiStrm
;
3526 DWORD ret
= MMSYSERR_NOERROR
;
3528 TRACE("(%08x)!\n", hMidiStrm
);
3530 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3531 ret
= MMSYSERR_INVALHANDLE
;
3533 if (SuspendThread(lpMidiStrm
->hThread
) == 0xFFFFFFFF) {
3534 WARN("bad Suspend (%ld)\n", GetLastError());
3535 ret
= MMSYSERR_ERROR
;
3541 /**************************************************************************
3542 * midiStreamPosition [WINMM.@]
3544 MMRESULT WINAPI
midiStreamPosition(HMIDISTRM hMidiStrm
, LPMMTIME lpMMT
, UINT cbmmt
)
3546 WINE_MIDIStream
* lpMidiStrm
;
3547 DWORD ret
= MMSYSERR_NOERROR
;
3549 TRACE("(%08x, %p, %u)!\n", hMidiStrm
, lpMMT
, cbmmt
);
3551 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3552 ret
= MMSYSERR_INVALHANDLE
;
3553 } else if (lpMMT
== NULL
|| cbmmt
!= sizeof(MMTIME
)) {
3554 ret
= MMSYSERR_INVALPARAM
;
3556 switch (lpMMT
->wType
) {
3558 lpMMT
->u
.ms
= lpMidiStrm
->dwPositionMS
;
3559 TRACE("=> %ld ms\n", lpMMT
->u
.ms
);
3562 lpMMT
->u
.ticks
= lpMidiStrm
->dwPulses
;
3563 TRACE("=> %ld ticks\n", lpMMT
->u
.ticks
);
3566 WARN("Unsupported time type %d\n", lpMMT
->wType
);
3567 lpMMT
->wType
= TIME_MS
;
3568 ret
= MMSYSERR_INVALPARAM
;
3575 /**************************************************************************
3576 * midiStreamProperty [WINMM.@]
3578 MMRESULT WINAPI
midiStreamProperty(HMIDISTRM hMidiStrm
, LPBYTE lpPropData
, DWORD dwProperty
)
3580 WINE_MIDIStream
* lpMidiStrm
;
3581 MMRESULT ret
= MMSYSERR_NOERROR
;
3583 TRACE("(%08x, %p, %lx)\n", hMidiStrm
, lpPropData
, dwProperty
);
3585 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3586 ret
= MMSYSERR_INVALHANDLE
;
3587 } else if ((dwProperty
& (MIDIPROP_GET
|MIDIPROP_SET
)) == 0) {
3588 ret
= MMSYSERR_INVALPARAM
;
3589 } else if (dwProperty
& MIDIPROP_TEMPO
) {
3590 MIDIPROPTEMPO
* mpt
= (MIDIPROPTEMPO
*)lpPropData
;
3592 if (sizeof(MIDIPROPTEMPO
) != mpt
->cbStruct
) {
3593 ret
= MMSYSERR_INVALPARAM
;
3594 } else if (dwProperty
& MIDIPROP_SET
) {
3595 lpMidiStrm
->dwTempo
= mpt
->dwTempo
;
3596 TRACE("Setting tempo to %ld\n", mpt
->dwTempo
);
3597 } else if (dwProperty
& MIDIPROP_GET
) {
3598 mpt
->dwTempo
= lpMidiStrm
->dwTempo
;
3599 TRACE("Getting tempo <= %ld\n", mpt
->dwTempo
);
3601 } else if (dwProperty
& MIDIPROP_TIMEDIV
) {
3602 MIDIPROPTIMEDIV
* mptd
= (MIDIPROPTIMEDIV
*)lpPropData
;
3604 if (sizeof(MIDIPROPTIMEDIV
) != mptd
->cbStruct
) {
3605 ret
= MMSYSERR_INVALPARAM
;
3606 } else if (dwProperty
& MIDIPROP_SET
) {
3607 lpMidiStrm
->dwTimeDiv
= mptd
->dwTimeDiv
;
3608 TRACE("Setting time div to %ld\n", mptd
->dwTimeDiv
);
3609 } else if (dwProperty
& MIDIPROP_GET
) {
3610 mptd
->dwTimeDiv
= lpMidiStrm
->dwTimeDiv
;
3611 TRACE("Getting time div <= %ld\n", mptd
->dwTimeDiv
);
3614 ret
= MMSYSERR_INVALPARAM
;
3620 /**************************************************************************
3621 * midiStreamRestart [WINMM.@]
3623 MMRESULT WINAPI
midiStreamRestart(HMIDISTRM hMidiStrm
)
3625 WINE_MIDIStream
* lpMidiStrm
;
3626 MMRESULT ret
= MMSYSERR_NOERROR
;
3628 TRACE("(%08x)!\n", hMidiStrm
);
3630 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3631 ret
= MMSYSERR_INVALHANDLE
;
3635 /* since we increase the thread suspend count on each midiStreamPause
3636 * there may be a need for several midiStreamResume
3639 ret
= ResumeThread(lpMidiStrm
->hThread
);
3640 } while (ret
!= 0xFFFFFFFF && ret
!= 0);
3641 if (ret
== 0xFFFFFFFF) {
3642 WARN("bad Resume (%ld)\n", GetLastError());
3643 ret
= MMSYSERR_ERROR
;
3645 lpMidiStrm
->dwStartTicks
= GetTickCount() - lpMidiStrm
->dwPositionMS
;
3651 /**************************************************************************
3652 * midiStreamStop [WINMM.@]
3654 MMRESULT WINAPI
midiStreamStop(HMIDISTRM hMidiStrm
)
3656 WINE_MIDIStream
* lpMidiStrm
;
3657 MMRESULT ret
= MMSYSERR_NOERROR
;
3659 TRACE("(%08x)!\n", hMidiStrm
);
3661 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3662 ret
= MMSYSERR_INVALHANDLE
;
3664 /* in case stream has been paused... FIXME is the current state correct ? */
3665 midiStreamRestart(hMidiStrm
);
3666 MMSYSTEM_MidiStream_PostMessage(lpMidiStrm
, WINE_MSM_STOP
, 0, 0);
3671 /**************************************************************************
3672 * midiStreamClose [MMSYSTEM.252]
3674 MMRESULT16 WINAPI
midiStreamClose16(HMIDISTRM16 hMidiStrm
)
3676 return midiStreamClose(hMidiStrm
);
3679 /**************************************************************************
3680 * midiStreamOpen [MMSYSTEM.251]
3682 MMRESULT16 WINAPI
midiStreamOpen16(HMIDISTRM16
* phMidiStrm
, LPUINT16 devid
,
3683 DWORD cMidi
, DWORD dwCallback
,
3684 DWORD dwInstance
, DWORD fdwOpen
)
3686 HMIDISTRM hMidiStrm32
;
3690 if (!phMidiStrm
|| !devid
)
3691 return MMSYSERR_INVALPARAM
;
3693 ret
= MMSYSTEM_MidiStream_Open(&hMidiStrm32
, &devid32
, cMidi
, dwCallback
,
3694 dwInstance
, fdwOpen
, FALSE
);
3695 *phMidiStrm
= hMidiStrm32
;
3700 /**************************************************************************
3701 * midiStreamOut [MMSYSTEM.254]
3703 MMRESULT16 WINAPI
midiStreamOut16(HMIDISTRM16 hMidiStrm
, LPMIDIHDR16 lpMidiHdr
, UINT16 cbMidiHdr
)
3705 return midiStreamOut(hMidiStrm
, (LPMIDIHDR
)lpMidiHdr
, cbMidiHdr
);
3708 /**************************************************************************
3709 * midiStreamPause [MMSYSTEM.255]
3711 MMRESULT16 WINAPI
midiStreamPause16(HMIDISTRM16 hMidiStrm
)
3713 return midiStreamPause(hMidiStrm
);
3716 /**************************************************************************
3717 * midiStreamPosition [MMSYSTEM.253]
3719 MMRESULT16 WINAPI
midiStreamPosition16(HMIDISTRM16 hMidiStrm
, LPMMTIME16 lpmmt16
, UINT16 cbmmt
)
3725 return MMSYSERR_INVALPARAM
;
3726 MMSYSTEM_MMTIME16to32(&mmt32
, lpmmt16
);
3727 ret
= midiStreamPosition(hMidiStrm
, &mmt32
, sizeof(MMTIME
));
3728 MMSYSTEM_MMTIME32to16(lpmmt16
, &mmt32
);
3732 /**************************************************************************
3733 * midiStreamProperty [MMSYSTEM.250]
3735 MMRESULT16 WINAPI
midiStreamProperty16(HMIDISTRM16 hMidiStrm
, LPBYTE lpPropData
, DWORD dwProperty
)
3737 return midiStreamProperty(hMidiStrm
, lpPropData
, dwProperty
);
3740 /**************************************************************************
3741 * midiStreamRestart [MMSYSTEM.256]
3743 MMRESULT16 WINAPI
midiStreamRestart16(HMIDISTRM16 hMidiStrm
)
3745 return midiStreamRestart(hMidiStrm
);
3748 /**************************************************************************
3749 * midiStreamStop [MMSYSTEM.257]
3751 MMRESULT16 WINAPI
midiStreamStop16(HMIDISTRM16 hMidiStrm
)
3753 return midiStreamStop(hMidiStrm
);
3756 static UINT WINAPI
MMSYSTEM_waveOpen(HANDLE
* lphndl
, UINT uDeviceID
, UINT uType
,
3757 const LPWAVEFORMATEX lpFormat
,
3758 DWORD dwCallback
, DWORD dwInstance
,
3759 DWORD dwFlags
, BOOL bFrom32
)
3763 DWORD dwRet
= MMSYSERR_NOERROR
;
3766 TRACE("(%p, %d, %s, %p, %08lX, %08lX, %08lX, %d);\n",
3767 lphndl
, (int)uDeviceID
, (uType
==MMDRV_WAVEOUT
)?"Out":"In", lpFormat
, dwCallback
,
3768 dwInstance
, dwFlags
, bFrom32
?32:16);
3770 if (dwFlags
& WAVE_FORMAT_QUERY
) TRACE("WAVE_FORMAT_QUERY requested !\n");
3772 if (lpFormat
== NULL
) return WAVERR_BADFORMAT
;
3773 if ((dwFlags
& WAVE_MAPPED
) && (uDeviceID
== (UINT
)-1))
3774 return MMSYSERR_INVALPARAM
;
3776 TRACE("wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u\n",
3777 lpFormat
->wFormatTag
, lpFormat
->nChannels
, lpFormat
->nSamplesPerSec
,
3778 lpFormat
->nAvgBytesPerSec
, lpFormat
->nBlockAlign
, lpFormat
->wBitsPerSample
, lpFormat
->cbSize
);
3780 if ((wmld
= MMDRV_Alloc(sizeof(WINE_WAVE
), uType
, &handle
,
3781 &dwFlags
, &dwCallback
, &dwInstance
, bFrom32
)) == NULL
)
3782 return MMSYSERR_NOMEM
;
3785 wod
.lpFormat
= lpFormat
; /* should the struct be copied iso pointer? */
3786 wod
.dwCallback
= dwCallback
;
3787 wod
.dwInstance
= dwInstance
;
3790 if (dwFlags
& WAVE_MAPPED
) {
3791 wod
.uMappedDeviceID
= uDeviceID
;
3792 uDeviceID
= WAVE_MAPPER
;
3794 wod
.uMappedDeviceID
= -1;
3796 wmld
->uDeviceID
= uDeviceID
;
3798 dwRet
= MMDRV_Open(wmld
, (uType
== MMDRV_WAVEOUT
) ? WODM_OPEN
: WIDM_OPEN
, (DWORD
)&wod
, dwFlags
);
3800 if ((dwFlags
& WAVE_FORMAT_QUERY
) || dwRet
!= MMSYSERR_NOERROR
) {
3801 MMDRV_Free(handle
, wmld
);
3805 if (lphndl
!= NULL
) *lphndl
= handle
;
3806 TRACE("=> %ld hWave=%04x\n", dwRet
, handle
);
3811 /**************************************************************************
3812 * waveOutGetNumDevs [WINMM.@]
3814 UINT WINAPI
waveOutGetNumDevs(void)
3816 return MMDRV_GetNum(MMDRV_WAVEOUT
);
3819 /**************************************************************************
3820 * waveOutGetNumDevs [MMSYSTEM.401]
3822 UINT16 WINAPI
waveOutGetNumDevs16(void)
3824 return MMDRV_GetNum(MMDRV_WAVEOUT
);
3827 /**************************************************************************
3828 * waveOutGetDevCaps [MMSYSTEM.402]
3830 UINT16 WINAPI
waveOutGetDevCaps16(UINT16 uDeviceID
,
3831 LPWAVEOUTCAPS16 lpCaps
, UINT16 uSize
)
3836 TRACE("(%u %p %u)!\n", uDeviceID
, lpCaps
, uSize
);
3837 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
3839 ret
= waveOutGetDevCapsA(uDeviceID
, &wocA
, sizeof(wocA
));
3841 if (ret
== MMSYSERR_NOERROR
) {
3842 lpCaps
->wMid
= wocA
.wMid
;
3843 lpCaps
->wPid
= wocA
.wPid
;
3844 lpCaps
->vDriverVersion
= wocA
.vDriverVersion
;
3845 strcpy(lpCaps
->szPname
, wocA
.szPname
);
3846 lpCaps
->dwFormats
= wocA
.dwFormats
;
3847 lpCaps
->wChannels
= wocA
.wChannels
;
3848 lpCaps
->dwSupport
= wocA
.dwSupport
;
3853 /**************************************************************************
3854 * waveOutGetDevCapsA [WINMM.@]
3856 UINT WINAPI
waveOutGetDevCapsA(UINT uDeviceID
, LPWAVEOUTCAPSA lpCaps
,
3861 TRACE("(%u %p %u)!\n", uDeviceID
, lpCaps
, uSize
);
3863 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
3865 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_WAVEOUT
, TRUE
)) == NULL
)
3866 return MMSYSERR_INVALHANDLE
;
3868 return MMDRV_Message(wmld
, WODM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
3872 /**************************************************************************
3873 * waveOutGetDevCapsW [WINMM.@]
3875 UINT WINAPI
waveOutGetDevCapsW(UINT uDeviceID
, LPWAVEOUTCAPSW lpCaps
,
3881 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
3883 ret
= waveOutGetDevCapsA(uDeviceID
, &wocA
, sizeof(wocA
));
3885 if (ret
== MMSYSERR_NOERROR
) {
3886 lpCaps
->wMid
= wocA
.wMid
;
3887 lpCaps
->wPid
= wocA
.wPid
;
3888 lpCaps
->vDriverVersion
= wocA
.vDriverVersion
;
3889 MultiByteToWideChar( CP_ACP
, 0, wocA
.szPname
, -1, lpCaps
->szPname
,
3890 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
3891 lpCaps
->dwFormats
= wocA
.dwFormats
;
3892 lpCaps
->wChannels
= wocA
.wChannels
;
3893 lpCaps
->dwSupport
= wocA
.dwSupport
;
3898 /**************************************************************************
3899 * WAVE_GetErrorText [internal]
3901 static UINT16
WAVE_GetErrorText(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
3903 UINT16 ret
= MMSYSERR_BADERRNUM
;
3905 if (lpText
== NULL
) {
3906 ret
= MMSYSERR_INVALPARAM
;
3907 } else if (uSize
== 0) {
3908 ret
= MMSYSERR_NOERROR
;
3910 /* test has been removed 'coz MMSYSERR_BASE is 0, and gcc did emit
3911 * a warning for the test was always true */
3912 (/*uError >= MMSYSERR_BASE && */uError
<= MMSYSERR_LASTERROR
) ||
3913 (uError
>= WAVERR_BASE
&& uError
<= WAVERR_LASTERROR
)) {
3915 if (LoadStringA(MULTIMEDIA_GetIData()->hWinMM32Instance
,
3916 uError
, lpText
, uSize
) > 0) {
3917 ret
= MMSYSERR_NOERROR
;
3923 /**************************************************************************
3924 * waveOutGetErrorText [MMSYSTEM.403]
3926 UINT16 WINAPI
waveOutGetErrorText16(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
3928 return WAVE_GetErrorText(uError
, lpText
, uSize
);
3931 /**************************************************************************
3932 * waveOutGetErrorTextA [WINMM.@]
3934 UINT WINAPI
waveOutGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
3936 return WAVE_GetErrorText(uError
, lpText
, uSize
);
3939 /**************************************************************************
3940 * waveOutGetErrorTextW [WINMM.@]
3942 UINT WINAPI
waveOutGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
3944 LPSTR xstr
= HeapAlloc(GetProcessHeap(), 0, uSize
);
3945 UINT ret
= WAVE_GetErrorText(uError
, xstr
, uSize
);
3947 MultiByteToWideChar( CP_ACP
, 0, xstr
, -1, lpText
, uSize
);
3948 HeapFree(GetProcessHeap(), 0, xstr
);
3952 /**************************************************************************
3953 * waveOutOpen [WINMM.@]
3954 * All the args/structs have the same layout as the win16 equivalents
3956 UINT WINAPI
waveOutOpen(HWAVEOUT
* lphWaveOut
, UINT uDeviceID
,
3957 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
3958 DWORD dwInstance
, DWORD dwFlags
)
3960 return MMSYSTEM_waveOpen(lphWaveOut
, uDeviceID
, MMDRV_WAVEOUT
, lpFormat
,
3961 dwCallback
, dwInstance
, dwFlags
, TRUE
);
3964 /**************************************************************************
3965 * waveOutOpen [MMSYSTEM.404]
3967 UINT16 WINAPI
waveOutOpen16(HWAVEOUT16
* lphWaveOut
, UINT16 uDeviceID
,
3968 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
3969 DWORD dwInstance
, DWORD dwFlags
)
3974 /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
3975 * call the 32 bit version
3976 * however, we need to promote correctly the wave mapper id
3977 * (0xFFFFFFFF and not 0x0000FFFF)
3979 ret
= MMSYSTEM_waveOpen(&hWaveOut
, (uDeviceID
== (UINT16
)-1) ? (UINT
)-1 : uDeviceID
,
3980 MMDRV_WAVEOUT
, lpFormat
, dwCallback
, dwInstance
, dwFlags
, FALSE
);
3982 if (lphWaveOut
!= NULL
) *lphWaveOut
= hWaveOut
;
3986 /**************************************************************************
3987 * waveOutClose [WINMM.@]
3989 UINT WINAPI
waveOutClose(HWAVEOUT hWaveOut
)
3994 TRACE("(%04X)\n", hWaveOut
);
3996 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
3997 return MMSYSERR_INVALHANDLE
;
3999 dwRet
= MMDRV_Close(wmld
, WODM_CLOSE
);
4000 MMDRV_Free(hWaveOut
, wmld
);
4005 /**************************************************************************
4006 * waveOutClose [MMSYSTEM.405]
4008 UINT16 WINAPI
waveOutClose16(HWAVEOUT16 hWaveOut
)
4013 ReleaseThunkLock(&level
);
4014 ret
= waveOutClose(hWaveOut
);
4015 RestoreThunkLock(level
);
4019 /**************************************************************************
4020 * waveOutPrepareHeader [WINMM.@]
4022 UINT WINAPI
waveOutPrepareHeader(HWAVEOUT hWaveOut
,
4023 WAVEHDR
* lpWaveOutHdr
, UINT uSize
)
4027 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpWaveOutHdr
, uSize
);
4029 if (lpWaveOutHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4031 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4032 return MMSYSERR_INVALHANDLE
;
4034 return MMDRV_Message(wmld
, WODM_PREPARE
, (DWORD
)lpWaveOutHdr
, uSize
, TRUE
);
4037 /**************************************************************************
4038 * waveOutPrepareHeader [MMSYSTEM.406]
4040 UINT16 WINAPI
waveOutPrepareHeader16(HWAVEOUT16 hWaveOut
, /* [in] */
4041 SEGPTR lpsegWaveOutHdr
, /* [???] */
4042 UINT16 uSize
) /* [in] */
4045 LPWAVEHDR lpWaveOutHdr
= MapSL(lpsegWaveOutHdr
);
4047 TRACE("(%04X, %08lx, %u);\n", hWaveOut
, lpsegWaveOutHdr
, uSize
);
4049 if (lpWaveOutHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4051 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4052 return MMSYSERR_INVALHANDLE
;
4054 return MMDRV_Message(wmld
, WODM_PREPARE
, (DWORD
)lpsegWaveOutHdr
, uSize
, FALSE
);
4057 /**************************************************************************
4058 * waveOutUnprepareHeader [WINMM.@]
4060 UINT WINAPI
waveOutUnprepareHeader(HWAVEOUT hWaveOut
,
4061 LPWAVEHDR lpWaveOutHdr
, UINT uSize
)
4065 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpWaveOutHdr
, uSize
);
4067 if (!(lpWaveOutHdr
->dwFlags
& WHDR_PREPARED
)) {
4068 return MMSYSERR_NOERROR
;
4071 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4072 return MMSYSERR_INVALHANDLE
;
4074 return MMDRV_Message(wmld
, WODM_UNPREPARE
, (DWORD
)lpWaveOutHdr
, uSize
, TRUE
);
4077 /**************************************************************************
4078 * waveOutUnprepareHeader [MMSYSTEM.407]
4080 UINT16 WINAPI
waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut
, /* [in] */
4081 SEGPTR lpsegWaveOutHdr
, /* [???] */
4082 UINT16 uSize
) /* [in] */
4085 LPWAVEHDR lpWaveOutHdr
= MapSL(lpsegWaveOutHdr
);
4087 TRACE("(%04X, %08lx, %u);\n", hWaveOut
, lpsegWaveOutHdr
, uSize
);
4089 if (!(lpWaveOutHdr
->dwFlags
& WHDR_PREPARED
)) {
4090 return MMSYSERR_NOERROR
;
4093 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4094 return MMSYSERR_INVALHANDLE
;
4096 return MMDRV_Message(wmld
, WODM_UNPREPARE
, (DWORD
)lpsegWaveOutHdr
, uSize
, FALSE
);
4099 /**************************************************************************
4100 * waveOutWrite [WINMM.@]
4102 UINT WINAPI
waveOutWrite(HWAVEOUT hWaveOut
, LPWAVEHDR lpWaveOutHdr
,
4107 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpWaveOutHdr
, uSize
);
4109 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4110 return MMSYSERR_INVALHANDLE
;
4112 return MMDRV_Message(wmld
, WODM_WRITE
, (DWORD
)lpWaveOutHdr
, uSize
, TRUE
);
4115 /**************************************************************************
4116 * waveOutWrite [MMSYSTEM.408]
4118 UINT16 WINAPI
waveOutWrite16(HWAVEOUT16 hWaveOut
, /* [in] */
4119 LPWAVEHDR lpsegWaveOutHdr
, /* [???] NOTE: SEGPTR */
4120 UINT16 uSize
) /* [in] */
4124 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpsegWaveOutHdr
, uSize
);
4126 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4127 return MMSYSERR_INVALHANDLE
;
4129 return MMDRV_Message(wmld
, WODM_WRITE
, (DWORD
)lpsegWaveOutHdr
, uSize
, FALSE
);
4132 /**************************************************************************
4133 * waveOutBreakLoop [WINMM.@]
4135 UINT WINAPI
waveOutBreakLoop(HWAVEOUT hWaveOut
)
4139 TRACE("(%04X);\n", hWaveOut
);
4141 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4142 return MMSYSERR_INVALHANDLE
;
4143 return MMDRV_Message(wmld
, WODM_BREAKLOOP
, 0L, 0L, TRUE
);
4146 /**************************************************************************
4147 * waveOutBreakLoop [MMSYSTEM.419]
4149 UINT16 WINAPI
waveOutBreakLoop16(HWAVEOUT16 hWaveOut16
)
4154 ReleaseThunkLock(&level
);
4155 ret
= waveOutBreakLoop(hWaveOut16
);
4156 RestoreThunkLock(level
);
4160 /**************************************************************************
4161 * waveOutPause [WINMM.@]
4163 UINT WINAPI
waveOutPause(HWAVEOUT hWaveOut
)
4167 TRACE("(%04X);\n", hWaveOut
);
4169 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4170 return MMSYSERR_INVALHANDLE
;
4171 return MMDRV_Message(wmld
, WODM_PAUSE
, 0L, 0L, TRUE
);
4174 /**************************************************************************
4175 * waveOutPause [MMSYSTEM.409]
4177 UINT16 WINAPI
waveOutPause16(HWAVEOUT16 hWaveOut16
)
4182 ReleaseThunkLock(&level
);
4183 ret
= waveOutPause(hWaveOut16
);
4184 RestoreThunkLock(level
);
4188 /**************************************************************************
4189 * waveOutReset [WINMM.@]
4191 UINT WINAPI
waveOutReset(HWAVEOUT hWaveOut
)
4195 TRACE("(%04X);\n", hWaveOut
);
4197 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4198 return MMSYSERR_INVALHANDLE
;
4199 return MMDRV_Message(wmld
, WODM_RESET
, 0L, 0L, TRUE
);
4202 /**************************************************************************
4203 * waveOutReset [MMSYSTEM.411]
4205 UINT16 WINAPI
waveOutReset16(HWAVEOUT16 hWaveOut16
)
4210 ReleaseThunkLock(&level
);
4211 ret
= waveOutReset(hWaveOut16
);
4212 RestoreThunkLock(level
);
4216 /**************************************************************************
4217 * waveOutRestart [WINMM.@]
4219 UINT WINAPI
waveOutRestart(HWAVEOUT hWaveOut
)
4223 TRACE("(%04X);\n", hWaveOut
);
4225 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4226 return MMSYSERR_INVALHANDLE
;
4227 return MMDRV_Message(wmld
, WODM_RESTART
, 0L, 0L, TRUE
);
4230 /**************************************************************************
4231 * waveOutRestart [MMSYSTEM.410]
4233 UINT16 WINAPI
waveOutRestart16(HWAVEOUT16 hWaveOut16
)
4238 ReleaseThunkLock(&level
);
4239 ret
= waveOutRestart(hWaveOut16
);
4240 RestoreThunkLock(level
);
4244 /**************************************************************************
4245 * waveOutGetPosition [WINMM.@]
4247 UINT WINAPI
waveOutGetPosition(HWAVEOUT hWaveOut
, LPMMTIME lpTime
,
4252 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpTime
, uSize
);
4254 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4255 return MMSYSERR_INVALHANDLE
;
4257 return MMDRV_Message(wmld
, WODM_GETPOS
, (DWORD
)lpTime
, uSize
, TRUE
);
4260 /**************************************************************************
4261 * waveOutGetPosition [MMSYSTEM.412]
4263 UINT16 WINAPI
waveOutGetPosition16(HWAVEOUT16 hWaveOut
, LPMMTIME16 lpTime
,
4269 mmt
.wType
= lpTime
->wType
;
4270 ret
= waveOutGetPosition(hWaveOut
, &mmt
, sizeof(mmt
));
4271 MMSYSTEM_MMTIME32to16(lpTime
, &mmt
);
4275 /**************************************************************************
4276 * waveOutGetPitch [WINMM.@]
4278 UINT WINAPI
waveOutGetPitch(HWAVEOUT hWaveOut
, LPDWORD lpdw
)
4282 TRACE("(%04X, %08lx);\n", hWaveOut
, (DWORD
)lpdw
);
4284 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4285 return MMSYSERR_INVALHANDLE
;
4286 return MMDRV_Message(wmld
, WODM_GETPITCH
, (DWORD
)lpdw
, 0L, TRUE
);
4289 /**************************************************************************
4290 * waveOutGetPitch [MMSYSTEM.413]
4292 UINT16 WINAPI
waveOutGetPitch16(HWAVEOUT16 hWaveOut16
, LPDWORD lpdw
)
4294 return waveOutGetPitch(hWaveOut16
, lpdw
);
4297 /**************************************************************************
4298 * waveOutSetPitch [WINMM.@]
4300 UINT WINAPI
waveOutSetPitch(HWAVEOUT hWaveOut
, DWORD dw
)
4304 TRACE("(%04X, %08lx);\n", hWaveOut
, (DWORD
)dw
);
4306 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4307 return MMSYSERR_INVALHANDLE
;
4308 return MMDRV_Message(wmld
, WODM_SETPITCH
, dw
, 0L, TRUE
);
4311 /**************************************************************************
4312 * waveOutSetPitch [MMSYSTEM.414]
4314 UINT16 WINAPI
waveOutSetPitch16(HWAVEOUT16 hWaveOut16
, DWORD dw
)
4316 return waveOutSetPitch(hWaveOut16
, dw
);
4319 /**************************************************************************
4320 * waveOutGetPlaybackRate [WINMM.@]
4322 UINT WINAPI
waveOutGetPlaybackRate(HWAVEOUT hWaveOut
, LPDWORD lpdw
)
4326 TRACE("(%04X, %08lx);\n", hWaveOut
, (DWORD
)lpdw
);
4328 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4329 return MMSYSERR_INVALHANDLE
;
4330 return MMDRV_Message(wmld
, WODM_GETPLAYBACKRATE
, (DWORD
)lpdw
, 0L, TRUE
);
4333 /**************************************************************************
4334 * waveOutGetPlaybackRate [MMSYSTEM.417]
4336 UINT16 WINAPI
waveOutGetPlaybackRate16(HWAVEOUT16 hWaveOut16
, LPDWORD lpdw
)
4338 return waveOutGetPlaybackRate(hWaveOut16
, lpdw
);
4341 /**************************************************************************
4342 * waveOutSetPlaybackRate [WINMM.@]
4344 UINT WINAPI
waveOutSetPlaybackRate(HWAVEOUT hWaveOut
, DWORD dw
)
4348 TRACE("(%04X, %08lx);\n", hWaveOut
, (DWORD
)dw
);
4350 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4351 return MMSYSERR_INVALHANDLE
;
4352 return MMDRV_Message(wmld
, WODM_SETPLAYBACKRATE
, dw
, 0L, TRUE
);
4355 /**************************************************************************
4356 * waveOutSetPlaybackRate [MMSYSTEM.418]
4358 UINT16 WINAPI
waveOutSetPlaybackRate16(HWAVEOUT16 hWaveOut16
, DWORD dw
)
4360 return waveOutSetPlaybackRate(hWaveOut16
, dw
);
4363 /**************************************************************************
4364 * waveOutGetVolume [WINMM.@]
4366 UINT WINAPI
waveOutGetVolume(UINT devid
, LPDWORD lpdw
)
4370 TRACE("(%04X, %08lx);\n", devid
, (DWORD
)lpdw
);
4372 if ((wmld
= MMDRV_Get(devid
, MMDRV_WAVEOUT
, TRUE
)) == NULL
)
4373 return MMSYSERR_INVALHANDLE
;
4375 return MMDRV_Message(wmld
, WODM_GETVOLUME
, (DWORD
)lpdw
, 0L, TRUE
);
4378 /**************************************************************************
4379 * waveOutGetVolume [MMSYSTEM.415]
4381 UINT16 WINAPI
waveOutGetVolume16(UINT16 devid
, LPDWORD lpdw
)
4383 return waveOutGetVolume(devid
, lpdw
);
4386 /**************************************************************************
4387 * waveOutSetVolume [WINMM.@]
4389 UINT WINAPI
waveOutSetVolume(UINT devid
, DWORD dw
)
4393 TRACE("(%04X, %08lx);\n", devid
, dw
);
4395 if ((wmld
= MMDRV_Get(devid
, MMDRV_WAVEOUT
, TRUE
)) == NULL
)
4396 return MMSYSERR_INVALHANDLE
;
4398 return MMDRV_Message(wmld
, WODM_SETVOLUME
, dw
, 0L, TRUE
);
4401 /**************************************************************************
4402 * waveOutSetVolume [MMSYSTEM.416]
4404 UINT16 WINAPI
waveOutSetVolume16(UINT16 devid
, DWORD dw
)
4406 return waveOutSetVolume(devid
, dw
);
4409 /**************************************************************************
4410 * waveOutGetID [WINMM.@]
4412 UINT WINAPI
waveOutGetID(HWAVEOUT hWaveOut
, UINT
* lpuDeviceID
)
4416 TRACE("(%04X, %p);\n", hWaveOut
, lpuDeviceID
);
4418 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
4420 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4421 return MMSYSERR_INVALHANDLE
;
4423 *lpuDeviceID
= wmld
->uDeviceID
;
4427 /**************************************************************************
4428 * waveOutGetID [MMSYSTEM.420]
4430 UINT16 WINAPI
waveOutGetID16(HWAVEOUT16 hWaveOut
, UINT16
* lpuDeviceID
)
4434 TRACE("(%04X, %p);\n", hWaveOut
, lpuDeviceID
);
4436 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
4438 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4439 return MMSYSERR_INVALHANDLE
;
4441 *lpuDeviceID
= wmld
->uDeviceID
;
4445 /**************************************************************************
4446 * waveOutMessage [WINMM.@]
4448 DWORD WINAPI
waveOutMessage(HWAVEOUT hWaveOut
, UINT uMessage
,
4449 DWORD dwParam1
, DWORD dwParam2
)
4453 TRACE("(%04x, %u, %ld, %ld)\n", hWaveOut
, uMessage
, dwParam1
, dwParam2
);
4455 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
) {
4456 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, TRUE
)) != NULL
) {
4457 return MMDRV_PhysicalFeatures(wmld
, uMessage
, dwParam1
, dwParam2
);
4459 return MMSYSERR_INVALHANDLE
;
4463 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
4464 return MMSYSERR_INVALPARAM
;
4466 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
4469 /**************************************************************************
4470 * waveOutMessage [MMSYSTEM.421]
4472 DWORD WINAPI
waveOutMessage16(HWAVEOUT16 hWaveOut
, UINT16 uMessage
,
4473 DWORD dwParam1
, DWORD dwParam2
)
4477 TRACE("(%04x, %u, %ld, %ld)\n", hWaveOut
, uMessage
, dwParam1
, dwParam2
);
4479 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
) {
4480 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, TRUE
)) != NULL
) {
4481 return MMDRV_PhysicalFeatures(wmld
, uMessage
, dwParam1
, dwParam2
);
4483 return MMSYSERR_INVALHANDLE
;
4487 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
4488 return MMSYSERR_INVALPARAM
;
4490 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, FALSE
);
4493 /**************************************************************************
4494 * waveInGetNumDevs [WINMM.@]
4496 UINT WINAPI
waveInGetNumDevs(void)
4498 return MMDRV_GetNum(MMDRV_WAVEIN
);
4501 /**************************************************************************
4502 * waveInGetNumDevs [MMSYSTEM.501]
4504 UINT16 WINAPI
waveInGetNumDevs16(void)
4506 return MMDRV_GetNum(MMDRV_WAVEIN
);
4509 /**************************************************************************
4510 * waveInGetDevCapsW [WINMM.@]
4512 UINT WINAPI
waveInGetDevCapsW(UINT uDeviceID
, LPWAVEINCAPSW lpCaps
, UINT uSize
)
4515 UINT ret
= waveInGetDevCapsA(uDeviceID
, &wicA
, uSize
);
4517 if (ret
== MMSYSERR_NOERROR
) {
4518 lpCaps
->wMid
= wicA
.wMid
;
4519 lpCaps
->wPid
= wicA
.wPid
;
4520 lpCaps
->vDriverVersion
= wicA
.vDriverVersion
;
4521 MultiByteToWideChar( CP_ACP
, 0, wicA
.szPname
, -1, lpCaps
->szPname
,
4522 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
4523 lpCaps
->dwFormats
= wicA
.dwFormats
;
4524 lpCaps
->wChannels
= wicA
.wChannels
;
4530 /**************************************************************************
4531 * waveInGetDevCapsA [WINMM.@]
4533 UINT WINAPI
waveInGetDevCapsA(UINT uDeviceID
, LPWAVEINCAPSA lpCaps
, UINT uSize
)
4537 TRACE("(%u %p %u)!\n", uDeviceID
, lpCaps
, uSize
);
4539 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_WAVEIN
, TRUE
)) == NULL
)
4540 return MMSYSERR_INVALHANDLE
;
4542 return MMDRV_Message(wmld
, WIDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
4545 /**************************************************************************
4546 * waveInGetDevCaps [MMSYSTEM.502]
4548 UINT16 WINAPI
waveInGetDevCaps16(UINT16 uDeviceID
, LPWAVEINCAPS16 lpCaps
,
4552 UINT ret
= waveInGetDevCapsA(uDeviceID
, &wicA
, sizeof(wicA
));
4554 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
4556 if (ret
== MMSYSERR_NOERROR
) {
4557 lpCaps
->wMid
= wicA
.wMid
;
4558 lpCaps
->wPid
= wicA
.wPid
;
4559 lpCaps
->vDriverVersion
= wicA
.vDriverVersion
;
4560 strcpy(lpCaps
->szPname
, wicA
.szPname
);
4561 lpCaps
->dwFormats
= wicA
.dwFormats
;
4562 lpCaps
->wChannels
= wicA
.wChannels
;
4567 /**************************************************************************
4568 * waveInGetErrorTextA [WINMM.@]
4570 UINT WINAPI
waveInGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
4572 return WAVE_GetErrorText(uError
, lpText
, uSize
);
4575 /**************************************************************************
4576 * waveInGetErrorTextW [WINMM.@]
4578 UINT WINAPI
waveInGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
4580 LPSTR txt
= HeapAlloc(GetProcessHeap(), 0, uSize
);
4581 UINT ret
= WAVE_GetErrorText(uError
, txt
, uSize
);
4583 MultiByteToWideChar( CP_ACP
, 0, txt
, -1, lpText
, uSize
);
4584 HeapFree(GetProcessHeap(), 0, txt
);
4588 /**************************************************************************
4589 * waveInGetErrorText [MMSYSTEM.503]
4591 UINT16 WINAPI
waveInGetErrorText16(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
4593 return WAVE_GetErrorText(uError
, lpText
, uSize
);
4596 /**************************************************************************
4597 * waveInOpen [WINMM.@]
4599 UINT WINAPI
waveInOpen(HWAVEIN
* lphWaveIn
, UINT uDeviceID
,
4600 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
4601 DWORD dwInstance
, DWORD dwFlags
)
4603 return MMSYSTEM_waveOpen(lphWaveIn
, uDeviceID
, MMDRV_WAVEIN
, lpFormat
,
4604 dwCallback
, dwInstance
, dwFlags
, TRUE
);
4607 /**************************************************************************
4608 * waveInOpen [MMSYSTEM.504]
4610 UINT16 WINAPI
waveInOpen16(HWAVEIN16
* lphWaveIn
, UINT16 uDeviceID
,
4611 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
4612 DWORD dwInstance
, DWORD dwFlags
)
4617 /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
4618 * call the 32 bit version
4619 * however, we need to promote correctly the wave mapper id
4620 * (0xFFFFFFFF and not 0x0000FFFF)
4622 ret
= MMSYSTEM_waveOpen(&hWaveIn
, (uDeviceID
== (UINT16
)-1) ? (UINT
)-1 : uDeviceID
,
4623 MMDRV_WAVEIN
, lpFormat
, dwCallback
, dwInstance
, dwFlags
, FALSE
);
4625 if (lphWaveIn
!= NULL
) *lphWaveIn
= hWaveIn
;
4629 /**************************************************************************
4630 * waveInClose [WINMM.@]
4632 UINT WINAPI
waveInClose(HWAVEIN hWaveIn
)
4637 TRACE("(%04X)\n", hWaveIn
);
4639 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4640 return MMSYSERR_INVALHANDLE
;
4642 dwRet
= MMDRV_Message(wmld
, WIDM_CLOSE
, 0L, 0L, TRUE
);
4643 MMDRV_Free(hWaveIn
, wmld
);
4647 /**************************************************************************
4648 * waveInClose [MMSYSTEM.505]
4650 UINT16 WINAPI
waveInClose16(HWAVEIN16 hWaveIn
)
4655 ReleaseThunkLock(&level
);
4656 ret
= waveInClose(hWaveIn
);
4657 RestoreThunkLock(level
);
4661 /**************************************************************************
4662 * waveInPrepareHeader [WINMM.@]
4664 UINT WINAPI
waveInPrepareHeader(HWAVEIN hWaveIn
, WAVEHDR
* lpWaveInHdr
,
4669 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
4671 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4672 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4673 return MMSYSERR_INVALHANDLE
;
4675 lpWaveInHdr
->dwBytesRecorded
= 0;
4677 return MMDRV_Message(wmld
, WIDM_PREPARE
, (DWORD
)lpWaveInHdr
, uSize
, TRUE
);
4680 /**************************************************************************
4681 * waveInPrepareHeader [MMSYSTEM.506]
4683 UINT16 WINAPI
waveInPrepareHeader16(HWAVEIN16 hWaveIn
, /* [in] */
4684 SEGPTR lpsegWaveInHdr
, /* [???] */
4685 UINT16 uSize
) /* [in] */
4688 LPWAVEHDR lpWaveInHdr
= MapSL(lpsegWaveInHdr
);
4691 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
4693 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALHANDLE
;
4694 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4695 return MMSYSERR_INVALHANDLE
;
4697 lpWaveInHdr
->dwBytesRecorded
= 0;
4699 ret
= MMDRV_Message(wmld
, WIDM_PREPARE
, (DWORD
)lpsegWaveInHdr
, uSize
, FALSE
);
4703 /**************************************************************************
4704 * waveInUnprepareHeader [WINMM.@]
4706 UINT WINAPI
waveInUnprepareHeader(HWAVEIN hWaveIn
, WAVEHDR
* lpWaveInHdr
,
4711 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
4713 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4714 if (!(lpWaveInHdr
->dwFlags
& WHDR_PREPARED
)) {
4715 return MMSYSERR_NOERROR
;
4718 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4719 return MMSYSERR_INVALHANDLE
;
4721 return MMDRV_Message(wmld
, WIDM_UNPREPARE
, (DWORD
)lpWaveInHdr
, uSize
, TRUE
);
4724 /**************************************************************************
4725 * waveInUnprepareHeader [MMSYSTEM.507]
4727 UINT16 WINAPI
waveInUnprepareHeader16(HWAVEIN16 hWaveIn
, /* [in] */
4728 SEGPTR lpsegWaveInHdr
, /* [???] */
4729 UINT16 uSize
) /* [in] */
4732 LPWAVEHDR lpWaveInHdr
= MapSL(lpsegWaveInHdr
);
4734 TRACE("(%04X, %08lx, %u);\n", hWaveIn
, lpsegWaveInHdr
, uSize
);
4736 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4738 if (!(lpWaveInHdr
->dwFlags
& WHDR_PREPARED
)) {
4739 return MMSYSERR_NOERROR
;
4742 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4743 return MMSYSERR_INVALHANDLE
;
4745 return MMDRV_Message(wmld
, WIDM_UNPREPARE
, (DWORD
)lpsegWaveInHdr
, uSize
, FALSE
);
4748 /**************************************************************************
4749 * waveInAddBuffer [WINMM.@]
4751 UINT WINAPI
waveInAddBuffer(HWAVEIN hWaveIn
,
4752 WAVEHDR
* lpWaveInHdr
, UINT uSize
)
4756 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
4758 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4759 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4760 return MMSYSERR_INVALHANDLE
;
4762 return MMDRV_Message(wmld
, WIDM_ADDBUFFER
, (DWORD
)lpWaveInHdr
, uSize
, TRUE
);
4765 /**************************************************************************
4766 * waveInAddBuffer [MMSYSTEM.508]
4768 UINT16 WINAPI
waveInAddBuffer16(HWAVEIN16 hWaveIn
, /* [in] */
4769 WAVEHDR
* lpsegWaveInHdr
, /* [???] NOTE: SEGPTR */
4770 UINT16 uSize
) /* [in] */
4774 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpsegWaveInHdr
, uSize
);
4776 if (lpsegWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4777 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4778 return MMSYSERR_INVALHANDLE
;
4780 return MMDRV_Message(wmld
, WIDM_ADDBUFFER
, (DWORD
)lpsegWaveInHdr
, uSize
, FALSE
);
4783 /**************************************************************************
4784 * waveInReset [WINMM.@]
4786 UINT WINAPI
waveInReset(HWAVEIN hWaveIn
)
4790 TRACE("(%04X);\n", hWaveIn
);
4792 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4793 return MMSYSERR_INVALHANDLE
;
4795 return MMDRV_Message(wmld
, WIDM_RESET
, 0L, 0L, TRUE
);
4798 /**************************************************************************
4799 * waveInReset [MMSYSTEM.511]
4801 UINT16 WINAPI
waveInReset16(HWAVEIN16 hWaveIn16
)
4806 ReleaseThunkLock(&level
);
4807 ret
= waveInReset(hWaveIn16
);
4808 RestoreThunkLock(level
);
4812 /**************************************************************************
4813 * waveInStart [WINMM.@]
4815 UINT WINAPI
waveInStart(HWAVEIN hWaveIn
)
4819 TRACE("(%04X);\n", hWaveIn
);
4821 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4822 return MMSYSERR_INVALHANDLE
;
4824 return MMDRV_Message(wmld
, WIDM_START
, 0L, 0L, TRUE
);
4827 /**************************************************************************
4828 * waveInStart [MMSYSTEM.509]
4830 UINT16 WINAPI
waveInStart16(HWAVEIN16 hWaveIn16
)
4835 ReleaseThunkLock(&level
);
4836 ret
= waveInStart(hWaveIn16
);
4837 RestoreThunkLock(level
);
4841 /**************************************************************************
4842 * waveInStop [WINMM.@]
4844 UINT WINAPI
waveInStop(HWAVEIN hWaveIn
)
4848 TRACE("(%04X);\n", hWaveIn
);
4850 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4851 return MMSYSERR_INVALHANDLE
;
4853 return MMDRV_Message(wmld
,WIDM_STOP
, 0L, 0L, TRUE
);
4856 /**************************************************************************
4857 * waveInStop [MMSYSTEM.510]
4859 UINT16 WINAPI
waveInStop16(HWAVEIN16 hWaveIn16
)
4864 ReleaseThunkLock(&level
);
4865 ret
= waveInStop(hWaveIn16
);
4866 RestoreThunkLock(level
);
4870 /**************************************************************************
4871 * waveInGetPosition [WINMM.@]
4873 UINT WINAPI
waveInGetPosition(HWAVEIN hWaveIn
, LPMMTIME lpTime
,
4878 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpTime
, uSize
);
4880 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4881 return MMSYSERR_INVALHANDLE
;
4883 return MMDRV_Message(wmld
, WIDM_GETPOS
, (DWORD
)lpTime
, uSize
, TRUE
);
4886 /**************************************************************************
4887 * waveInGetPosition [MMSYSTEM.512]
4889 UINT16 WINAPI
waveInGetPosition16(HWAVEIN16 hWaveIn
, LPMMTIME16 lpTime
,
4895 mmt
.wType
= lpTime
->wType
;
4896 ret
= waveInGetPosition(hWaveIn
, &mmt
, sizeof(mmt
));
4897 MMSYSTEM_MMTIME32to16(lpTime
, &mmt
);
4901 /**************************************************************************
4902 * waveInGetID [WINMM.@]
4904 UINT WINAPI
waveInGetID(HWAVEIN hWaveIn
, UINT
* lpuDeviceID
)
4908 TRACE("(%04X, %p);\n", hWaveIn
, lpuDeviceID
);
4910 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
4912 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4913 return MMSYSERR_INVALHANDLE
;
4915 *lpuDeviceID
= wmld
->uDeviceID
;
4916 return MMSYSERR_NOERROR
;
4919 /**************************************************************************
4920 * waveInGetID [MMSYSTEM.513]
4922 UINT16 WINAPI
waveInGetID16(HWAVEIN16 hWaveIn
, UINT16
* lpuDeviceID
)
4926 TRACE("(%04X, %p);\n", hWaveIn
, lpuDeviceID
);
4928 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
4930 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4931 return MMSYSERR_INVALHANDLE
;
4933 *lpuDeviceID
= wmld
->uDeviceID
;
4934 return MMSYSERR_NOERROR
;
4937 /**************************************************************************
4938 * waveInMessage [WINMM.@]
4940 DWORD WINAPI
waveInMessage(HWAVEIN hWaveIn
, UINT uMessage
,
4941 DWORD dwParam1
, DWORD dwParam2
)
4945 TRACE("(%04x, %u, %ld, %ld)\n", hWaveIn
, uMessage
, dwParam1
, dwParam2
);
4948 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
4949 return MMSYSERR_INVALPARAM
;
4951 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4952 return MMSYSERR_INVALHANDLE
;
4954 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
4957 /**************************************************************************
4958 * waveInMessage [MMSYSTEM.514]
4960 DWORD WINAPI
waveInMessage16(HWAVEIN16 hWaveIn
, UINT16 uMessage
,
4961 DWORD dwParam1
, DWORD dwParam2
)
4965 TRACE("(%04x, %u, %ld, %ld)\n", hWaveIn
, uMessage
, dwParam1
, dwParam2
);
4968 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
4969 return MMSYSERR_INVALPARAM
;
4971 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4972 return MMSYSERR_INVALHANDLE
;
4974 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
4977 /*#define USE_MM_TSK_WINE*/
4979 /**************************************************************************
4980 * mmTaskCreate [MMSYSTEM.900]
4982 * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
4983 * called upon creation with dwPmt as parameter.
4985 HINSTANCE16 WINAPI
mmTaskCreate16(SEGPTR spProc
, HINSTANCE16
*lphMmTask
, DWORD dwPmt
)
4990 DWORD showCmd
= 0x40002;
4993 TRACE("(%08lx, %p, %08lx);\n", spProc
, lphMmTask
, dwPmt
);
4994 /* This to work requires NE modules to be started with a binary command line
4995 * which is not currently the case. A patch exists but has never been committed.
4996 * A workaround would be to integrate code for mmtask.tsk into Wine, but
4997 * this requires tremendous work (starting with patching tools/build to
4998 * create NE executables (and not only DLLs) for builtins modules.
5001 FIXME("This is currently broken. It will fail\n");
5004 *(LPDWORD
)(cmdline
+ 1) = (DWORD
)spProc
;
5005 *(LPDWORD
)(cmdline
+ 5) = dwPmt
;
5006 *(LPDWORD
)(cmdline
+ 9) = 0;
5008 lp
.hEnvironment
= 0;
5009 lp
.cmdLine
= MapLS(cmdline
);
5010 lp
.showCmd
= MapLS(&showCmd
);
5013 #ifndef USE_MM_TSK_WINE
5014 handle
= LoadModule16("c:\\windows\\system\\mmtask.tsk", &lp
);
5016 handle
= LoadModule16("mmtask.tsk", &lp
);
5019 ret
= (handle
) ? 1 : 2;
5025 *lphMmTask
= handle
;
5027 UnMapLS( lp
.cmdLine
);
5028 UnMapLS( lp
.showCmd
);
5029 TRACE("=> 0x%04x/%d\n", handle
, ret
);
5033 #ifdef USE_MM_TSK_WINE
5034 /* C equivalent to mmtask.tsk binary content */
5035 void mmTaskEntryPoint16(LPSTR cmdLine
, WORD di
, WORD si
)
5037 int len
= cmdLine
[0x80];
5040 void (*fpProc
)(DWORD
) = MapSL(*((DWORD
*)(cmdLine
+ 1)));
5041 DWORD dwPmt
= *((DWORD
*)(cmdLine
+ 5));
5044 InitTask16(); /* FIXME: pmts / from context ? */
5047 if (SetMessageQueue16(0x40)) {
5049 if (HIWORD(fpProc
)) {
5051 /* EPP StackEnter16(); */
5063 /**************************************************************************
5064 * mmTaskBlock [MMSYSTEM.902]
5066 void WINAPI
mmTaskBlock16(HINSTANCE16 WINE_UNUSED hInst
)
5071 GetMessageA(&msg
, 0, 0, 0);
5073 TranslateMessage(&msg
);
5074 DispatchMessageA(&msg
);
5076 } while (msg
.message
< 0x3A0);
5079 /**************************************************************************
5080 * mmTaskSignal [MMSYSTEM.903]
5082 LRESULT WINAPI
mmTaskSignal16(HTASK16 ht
)
5084 TRACE("(%04x);\n", ht
);
5085 return PostAppMessage16(ht
, WM_USER
, 0, 0);
5088 /**************************************************************************
5089 * mmGetCurrentTask [MMSYSTEM.904]
5091 HTASK16 WINAPI
mmGetCurrentTask16(void)
5093 return GetCurrentTask();
5096 /**************************************************************************
5097 * mmTaskYield [MMSYSTEM.905]
5099 void WINAPI
mmTaskYield16(void)
5103 if (PeekMessageA(&msg
, 0, 0, 0, 0)) {
5108 DWORD WINAPI
GetProcessFlags(DWORD
);
5110 /**************************************************************************
5111 * mmThreadCreate [MMSYSTEM.1120]
5114 * Creates a MM thread, calling fpThreadAddr(dwPmt).
5116 * bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
5117 * bit.1 set means to open a VxD for this thread (unsupported)
5119 LRESULT WINAPI
mmThreadCreate16(FARPROC16 fpThreadAddr
, LPHANDLE lpHndl
, DWORD dwPmt
, DWORD dwFlags
)
5124 TRACE("(%p, %p, %08lx, %08lx)!\n", fpThreadAddr
, lpHndl
, dwPmt
, dwFlags
);
5126 hndl
= GlobalAlloc16(sizeof(WINE_MMTHREAD
), GMEM_SHARE
|GMEM_ZEROINIT
);
5131 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5134 /* force mmtask routines even if mmthread is required */
5135 /* this will work only if the patch about binary cmd line and NE tasks
5141 lpMMThd
->dwSignature
= WINE_MMTHREAD_CREATED
;
5142 lpMMThd
->dwCounter
= 0;
5143 lpMMThd
->hThread
= 0;
5144 lpMMThd
->dwThreadID
= 0;
5145 lpMMThd
->fpThread
= fpThreadAddr
;
5146 lpMMThd
->dwThreadPmt
= dwPmt
;
5147 lpMMThd
->dwSignalCount
= 0;
5148 lpMMThd
->hEvent
= 0;
5150 lpMMThd
->dwStatus
= 0;
5151 lpMMThd
->dwFlags
= dwFlags
;
5154 if ((dwFlags
& 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
5155 lpMMThd
->hEvent
= CreateEventA(0, 0, 1, 0);
5157 TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd
);
5158 if (lpMMThd
->dwFlags
& 2) {
5159 /* as long as we don't support MM VxD in wine, we don't need
5160 * to care about this flag
5162 /* FIXME("Don't know how to properly open VxD handles\n"); */
5163 /* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
5166 lpMMThd
->hThread
= CreateThread(0, 0, (LPTHREAD_START_ROUTINE
)WINE_mmThreadEntryPoint
,
5167 (LPVOID
)(DWORD
)hndl
, CREATE_SUSPENDED
, &lpMMThd
->dwThreadID
);
5168 if (lpMMThd
->hThread
== 0) {
5169 WARN("Couldn't create thread\n");
5170 /* clean-up(VxDhandle...); devicedirectio... */
5171 if (lpMMThd
->hEvent
!= 0)
5172 CloseHandle(lpMMThd
->hEvent
);
5175 TRACE("Got a nice thread hndl=0x%04x id=0x%08lx\n", lpMMThd
->hThread
, lpMMThd
->dwThreadID
);
5179 /* get WINE_mmThreadEntryPoint()
5180 * 2047 is its ordinal in mmsystem.spec
5182 FARPROC16 fp
= GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (LPCSTR
)2047);
5184 TRACE("farproc seg=0x%08lx lin=%p\n", (DWORD
)fp
, MapSL((SEGPTR
)fp
));
5186 ret
= (fp
== 0) ? 2 : mmTaskCreate16((DWORD
)fp
, 0, hndl
);
5190 if (lpMMThd
->hThread
&& !ResumeThread(lpMMThd
->hThread
))
5191 WARN("Couldn't resume thread\n");
5193 while (lpMMThd
->dwStatus
!= 0x10) { /* test also HIWORD of dwStatus */
5207 TRACE("ok => %ld\n", ret
);
5211 /**************************************************************************
5212 * mmThreadSignal [MMSYSTEM.1121]
5214 void WINAPI
mmThreadSignal16(HANDLE16 hndl
)
5216 TRACE("(%04x)!\n", hndl
);
5219 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5221 lpMMThd
->dwCounter
++;
5222 if (lpMMThd
->hThread
!= 0) {
5223 InterlockedIncrement(&lpMMThd
->dwSignalCount
);
5224 SetEvent(lpMMThd
->hEvent
);
5226 mmTaskSignal16(lpMMThd
->hTask
);
5228 lpMMThd
->dwCounter
--;
5232 /**************************************************************************
5233 * MMSYSTEM_ThreadBlock [internal]
5235 static void MMSYSTEM_ThreadBlock(WINE_MMTHREAD
* lpMMThd
)
5240 if (lpMMThd
->dwThreadID
!= GetCurrentThreadId())
5241 ERR("Not called by thread itself\n");
5244 ResetEvent(lpMMThd
->hEvent
);
5245 if (InterlockedDecrement(&lpMMThd
->dwSignalCount
) >= 0)
5247 InterlockedIncrement(&lpMMThd
->dwSignalCount
);
5251 ret
= MsgWaitForMultipleObjects(1, &lpMMThd
->hEvent
, FALSE
, INFINITE
, QS_ALLINPUT
);
5253 case WAIT_OBJECT_0
: /* Event */
5256 case WAIT_OBJECT_0
+ 1: /* Msg */
5258 if (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) {
5259 TranslateMessage(&msg
);
5260 DispatchMessageA(&msg
);
5264 WARN("S2.x unsupported ret val 0x%08lx\n", ret
);
5270 /**************************************************************************
5271 * mmThreadBlock [MMSYSTEM.1122]
5273 void WINAPI
mmThreadBlock16(HANDLE16 hndl
)
5275 TRACE("(%04x)!\n", hndl
);
5278 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5280 if (lpMMThd
->hThread
!= 0) {
5283 ReleaseThunkLock(&lc
);
5284 MMSYSTEM_ThreadBlock(lpMMThd
);
5285 RestoreThunkLock(lc
);
5287 mmTaskBlock16(lpMMThd
->hTask
);
5293 /**************************************************************************
5294 * mmThreadIsCurrent [MMSYSTEM.1123]
5296 BOOL16 WINAPI
mmThreadIsCurrent16(HANDLE16 hndl
)
5300 TRACE("(%04x)!\n", hndl
);
5302 if (hndl
&& mmThreadIsValid16(hndl
)) {
5303 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5304 ret
= (GetCurrentThreadId() == lpMMThd
->dwThreadID
);
5306 TRACE("=> %d\n", ret
);
5310 /**************************************************************************
5311 * mmThreadIsValid [MMSYSTEM.1124]
5313 BOOL16 WINAPI
mmThreadIsValid16(HANDLE16 hndl
)
5317 TRACE("(%04x)!\n", hndl
);
5320 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5322 if (!IsBadWritePtr(lpMMThd
, sizeof(WINE_MMTHREAD
)) &&
5323 lpMMThd
->dwSignature
== WINE_MMTHREAD_CREATED
&&
5324 IsTask16(lpMMThd
->hTask
)) {
5325 lpMMThd
->dwCounter
++;
5326 if (lpMMThd
->hThread
!= 0) {
5328 if (GetExitCodeThread(lpMMThd
->hThread
, &dwThreadRet
) &&
5329 dwThreadRet
== STATUS_PENDING
) {
5335 lpMMThd
->dwCounter
--;
5338 TRACE("=> %d\n", ret
);
5342 /**************************************************************************
5343 * mmThreadGetTask [MMSYSTEM.1125]
5345 HANDLE16 WINAPI
mmThreadGetTask16(HANDLE16 hndl
)
5349 TRACE("(%04x)\n", hndl
);
5351 if (mmThreadIsValid16(hndl
)) {
5352 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5353 ret
= lpMMThd
->hTask
;
5358 /* ### start build ### */
5359 extern LONG CALLBACK
MMSYSTEM_CallTo16_long_l (FARPROC16
,LONG
);
5360 /* ### stop build ### */
5362 /**************************************************************************
5363 * __wine_mmThreadEntryPoint (MMSYSTEM.2047)
5365 void WINAPI
WINE_mmThreadEntryPoint(DWORD _pmt
)
5367 HANDLE16 hndl
= (HANDLE16
)_pmt
;
5368 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5370 TRACE("(%04x %p)\n", hndl
, lpMMThd
);
5372 lpMMThd
->hTask
= LOWORD(GetCurrentTask());
5373 TRACE("[10-%08x] setting hTask to 0x%08x\n", lpMMThd
->hThread
, lpMMThd
->hTask
);
5374 lpMMThd
->dwStatus
= 0x10;
5375 MMSYSTEM_ThreadBlock(lpMMThd
);
5376 TRACE("[20-%08x]\n", lpMMThd
->hThread
);
5377 lpMMThd
->dwStatus
= 0x20;
5378 if (lpMMThd
->fpThread
) {
5379 MMSYSTEM_CallTo16_long_l(lpMMThd
->fpThread
, lpMMThd
->dwThreadPmt
);
5381 lpMMThd
->dwStatus
= 0x30;
5382 TRACE("[30-%08x]\n", lpMMThd
->hThread
);
5383 while (lpMMThd
->dwCounter
) {
5385 /* K32WOWYield16();*/
5387 TRACE("[XX-%08x]\n", lpMMThd
->hThread
);
5389 lpMMThd
->dwSignature
= WINE_MMTHREAD_DELETED
;
5390 /* close lpMMThread->hVxD directIO */
5391 if (lpMMThd
->hEvent
)
5392 CloseHandle(lpMMThd
->hEvent
);
5397 typedef BOOL16 (WINAPI
*MMCPLCALLBACK
)(HWND
, LPCSTR
, LPCSTR
, LPCSTR
);
5399 /**************************************************************************
5400 * mmShowMMCPLPropertySheet [MMSYSTEM.1150]
5402 BOOL16 WINAPI
mmShowMMCPLPropertySheet16(HWND hWnd
, LPCSTR lpStrDevice
,
5403 LPCSTR lpStrTab
, LPCSTR lpStrTitle
)
5408 TRACE("(%04x \"%s\" \"%s\" \"%s\")\n", hWnd
, lpStrDevice
, lpStrTab
, lpStrTitle
);
5410 hndl
= LoadLibraryA("MMSYS.CPL");
5412 MMCPLCALLBACK fp
= (MMCPLCALLBACK
)GetProcAddress(hndl
, "ShowMMCPLPropertySheet");
5415 ReleaseThunkLock(&lc
);
5416 ret
= (fp
)(hWnd
, lpStrDevice
, lpStrTab
, lpStrTitle
);
5417 RestoreThunkLock(lc
);
5425 /**************************************************************************
5426 * StackEnter [MMSYSTEM.32]
5428 void WINAPI
StackEnter16(void)
5431 /* mmsystem.dll from Win 95 does only this: so does Wine */
5436 /**************************************************************************
5437 * StackLeave [MMSYSTEM.33]
5439 void WINAPI
StackLeave16(void)
5442 /* mmsystem.dll from Win 95 does only this: so does Wine */
5447 /**************************************************************************
5448 * WMMMidiRunOnce [MMSYSTEM.8]
5450 void WINAPI
WMMMidiRunOnce16(void)
5452 FIXME("(), stub!\n");
5455 /**************************************************************************
5456 * OutputDebugStr [MMSYSTEM.30]
5458 void WINAPI
OutputDebugStr16(
5459 LPCSTR str
) /* [in] The message to be logged and given to the debugger. */
5461 OutputDebugStringA( str
);