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 TRACE("Created IData (%p) for pid %08lx\n", iData
, iData
->dwThisProcess
);
100 /**************************************************************************
101 * MULTIMEDIA_DeleteIData [internal]
103 static void MULTIMEDIA_DeleteIData(void)
105 LPWINE_MM_IDATA iData
= MULTIMEDIA_GetIDataNoCheck();
106 LPWINE_MM_IDATA
* ppid
;
111 for (ppid
= &lpFirstIData
; *ppid
; ppid
= &(*ppid
)->lpNextIData
) {
112 if (*ppid
== iData
) {
113 *ppid
= iData
->lpNextIData
;
117 /* FIXME: should also free content and resources allocated
119 HeapFree(GetProcessHeap(), 0, iData
);
123 /**************************************************************************
124 * DllEntryPoint (WINMM.init)
126 * WINMM DLL entry point
129 BOOL WINAPI
WINMM_LibMain(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID fImpLoad
)
131 TRACE("0x%x 0x%lx %p\n", hInstDLL
, fdwReason
, fImpLoad
);
134 case DLL_PROCESS_ATTACH
:
135 if (!MULTIMEDIA_CreateIData(hInstDLL
))
137 if (!MULTIMEDIA_MciInit() || !MMDRV_Init()) {
138 MULTIMEDIA_DeleteIData();
142 case DLL_PROCESS_DETACH
:
143 MULTIMEDIA_DeleteIData();
145 case DLL_THREAD_ATTACH
:
146 case DLL_THREAD_DETACH
:
152 /**************************************************************************
153 * DllEntryPoint (MMSYSTEM.2046)
155 * MMSYSTEM DLL entry point
158 BOOL WINAPI
MMSYSTEM_LibMain(DWORD fdwReason
, HINSTANCE hinstDLL
, WORD ds
,
159 WORD wHeapSize
, DWORD dwReserved1
, WORD wReserved2
)
162 LPWINE_MM_IDATA iData
;
164 TRACE("0x%x 0x%lx\n", hinstDLL
, fdwReason
);
167 case DLL_PROCESS_ATTACH
:
168 /* need to load WinMM in order to:
169 * - initiate correctly shared variables (MULTIMEDIA_Init())
170 * - create correctly the per process WINE_MM_IDATA chunk
172 hndl
= LoadLibraryA("WINMM.DLL");
175 ERR("Could not load sibling WinMM.dll\n");
178 iData
= MULTIMEDIA_GetIData();
179 iData
->hWinMM16Instance
= hinstDLL
;
180 iData
->h16Module32
= hndl
;
182 case DLL_PROCESS_DETACH
:
183 iData
= MULTIMEDIA_GetIData();
184 FreeLibrary(iData
->h16Module32
);
186 case DLL_THREAD_ATTACH
:
187 case DLL_THREAD_DETACH
:
193 /**************************************************************************
194 * MMSYSTEM_WEP [MMSYSTEM.1]
196 int WINAPI
MMSYSTEM_WEP(HINSTANCE16 hInstance
, WORD wDataSeg
,
197 WORD cbHeapSize
, LPSTR lpCmdLine
)
199 FIXME("STUB: Unloading MMSystem DLL ... hInst=%04X \n", hInstance
);
203 void MMSYSTEM_MMTIME32to16(LPMMTIME16 mmt16
, const MMTIME
* mmt32
)
205 mmt16
->wType
= mmt32
->wType
;
206 /* layout of rest is the same for 32/16,
207 * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
209 memcpy(&(mmt16
->u
), &(mmt32
->u
), sizeof(mmt16
->u
));
212 void MMSYSTEM_MMTIME16to32(LPMMTIME mmt32
, const MMTIME16
* mmt16
)
214 mmt32
->wType
= mmt16
->wType
;
215 /* layout of rest is the same for 32/16,
216 * Note: mmt16->u is 2 bytes smaller than mmt32->u, which has padding
218 memcpy(&(mmt32
->u
), &(mmt16
->u
), sizeof(mmt16
->u
));
221 static HMMIO
get_mmioFromFile(LPCWSTR lpszName
)
227 ret
= mmioOpenW((LPWSTR
)lpszName
, NULL
,
228 MMIO_ALLOCBUF
| MMIO_READ
| MMIO_DENYWRITE
);
229 if (ret
!= 0) return ret
;
230 if (SearchPathW(NULL
, lpszName
, NULL
, sizeof(buf
)/sizeof(buf
[0]), buf
, &dummy
))
232 return mmioOpenW(buf
, NULL
,
233 MMIO_ALLOCBUF
| MMIO_READ
| MMIO_DENYWRITE
);
238 static HMMIO
get_mmioFromProfile(UINT uFlags
, LPCWSTR lpszName
)
243 HKEY hRegSnd
, hRegApp
, hScheme
, hSnd
;
244 DWORD err
, type
, count
;
246 static WCHAR wszSounds
[] = {'S','o','u','n','d','s',0};
247 static WCHAR wszDefault
[] = {'D','e','f','a','u','l','t',0};
248 static WCHAR wszKey
[] = {'A','p','p','E','v','e','n','t','s','\\','\\',
249 'S','c','h','e','m','e','s','\\','\\',
251 static WCHAR wszDotDefault
[] = {'.','D','e','f','a','u','l','t',0};
252 static WCHAR wszNull
[] = {0};
254 /* FIXME: we should also look up the registry under
255 * HKCU\AppEvents\Schemes\Apps\.Default
256 * HKCU\AppEvents\Schemes\Apps\<AppName>
259 TRACE("searching in SystemSound list for %s\n", debugstr_w(lpszName
));
260 GetProfileStringW(wszSounds
, (LPWSTR
)lpszName
, wszNull
, str
, sizeof(str
)/sizeof(str
[0]));
261 if (lstrlenW(str
) == 0)
263 if (uFlags
& SND_NODEFAULT
) goto next
;
264 GetProfileStringW(wszSounds
, wszDefault
, wszNull
, str
, sizeof(str
)/sizeof(str
[0]));
265 if (lstrlenW(str
) == 0) goto next
;
267 for (ptr
= str
; *ptr
&& *ptr
!= ','; ptr
++);
269 hmmio
= mmioOpenW(str
, NULL
, MMIO_ALLOCBUF
| MMIO_READ
| MMIO_DENYWRITE
);
270 if (hmmio
!= 0) return hmmio
;
272 if (RegOpenKeyW(HKEY_CURRENT_USER
, wszKey
, &hRegSnd
) != 0) goto none
;
273 if (uFlags
& SND_APPLICATION
)
276 if (GetModuleFileNameW(0, str
, sizeof(str
)/sizeof(str
[0])))
280 for (ptr
= str
+ lstrlenW(str
) - 1; ptr
>= str
; ptr
--)
282 if (*ptr
== '.') *ptr
= 0;
285 err
= RegOpenKeyW(hRegSnd
, str
, &hRegApp
);
293 err
= RegOpenKeyW(hRegSnd
, wszDotDefault
, &hRegApp
);
295 RegCloseKey(hRegSnd
);
296 if (err
!= 0) goto none
;
297 err
= RegOpenKeyW(hRegApp
, lpszName
, &hScheme
);
298 RegCloseKey(hRegApp
);
299 if (err
!= 0) goto none
;
300 err
= RegOpenKeyW(hScheme
, wszDotDefault
, &hSnd
);
301 RegCloseKey(hScheme
);
302 if (err
!= 0) goto none
;
303 count
= sizeof(str
)/sizeof(str
[0]);
304 err
= RegQueryValueExW(hSnd
, NULL
, 0, &type
, (LPBYTE
)str
, &count
);
306 if (err
!= 0) goto none
;
307 hmmio
= mmioOpenW(str
, NULL
, MMIO_ALLOCBUF
| MMIO_READ
| MMIO_DENYWRITE
);
308 if (hmmio
) return hmmio
;
310 WARN("can't find SystemSound='%s' !\n", debugstr_w(lpszName
));
314 struct playsound_data
320 static void CALLBACK
PlaySound_Callback(HWAVEOUT hwo
, UINT uMsg
,
322 DWORD dwParam1
, DWORD dwParam2
)
324 struct playsound_data
* s
= (struct playsound_data
*)dwInstance
;
331 InterlockedIncrement(&s
->dwEventCount
);
332 TRACE("Returning waveHdr=%lx\n", dwParam1
);
336 ERR("Unknown uMsg=%d\n", uMsg
);
340 static void PlaySound_WaitDone(struct playsound_data
* s
)
343 ResetEvent(s
->hEvent
);
344 if (InterlockedDecrement(&s
->dwEventCount
) >= 0) break;
345 InterlockedIncrement(&s
->dwEventCount
);
347 WaitForSingleObject(s
->hEvent
, INFINITE
);
351 static DWORD WINAPI
proc_PlaySound(LPVOID arg
)
353 WINE_PLAYSOUND
* wps
= (WINE_PLAYSOUND
*)arg
;
354 LPWINE_MM_IDATA iData
= MULTIMEDIA_GetIData();
359 LPWAVEFORMATEX lpWaveFormat
= NULL
;
361 LPWAVEHDR waveHdr
= NULL
;
362 INT count
, bufsize
, left
, index
;
363 struct playsound_data s
;
368 TRACE("SoundName='%s' !\n", debugstr_w(wps
->pszSound
));
370 /* if resource, grab it */
371 if ((wps
->fdwSound
& SND_RESOURCE
) == SND_RESOURCE
) {
372 static WCHAR wszWave
[] = {'W','A','V','E',0};
376 if ((hRes
= FindResourceW(wps
->hMod
, wps
->pszSound
, wszWave
)) == 0 ||
377 (hGlob
= LoadResource(wps
->hMod
, hRes
)) == 0)
379 if ((data
= LockResource(hGlob
)) == NULL
) {
385 data
= (void*)wps
->pszSound
;
387 /* construct an MMIO stream (either in memory, or from a file */
388 /* hmmio = 0; */ /* to catch errors */
389 if (wps
->fdwSound
& SND_MEMORY
)
390 { /* NOTE: SND_RESOURCE has the SND_MEMORY bit set */
393 memset(&mminfo
, 0, sizeof(mminfo
));
394 mminfo
.fccIOProc
= FOURCC_MEM
;
395 mminfo
.pchBuffer
= (LPSTR
)data
;
396 mminfo
.cchBuffer
= -1; /* FIXME: when a resource, could grab real size */
397 TRACE("Memory sound %p\n", data
);
398 hmmio
= mmioOpenW(NULL
, &mminfo
, MMIO_READ
);
400 else if (wps
->fdwSound
& SND_ALIAS
)
402 hmmio
= get_mmioFromProfile(wps
->fdwSound
, wps
->pszSound
);
404 else if (wps
->fdwSound
& SND_FILENAME
)
406 hmmio
= get_mmioFromFile(wps
->pszSound
);
410 if ((hmmio
= get_mmioFromProfile(wps
->fdwSound
| SND_NODEFAULT
, wps
->pszSound
)) == 0)
412 if ((hmmio
= get_mmioFromFile(wps
->pszSound
)) == 0)
414 hmmio
= get_mmioFromProfile(wps
->fdwSound
, wps
->pszSound
);
418 if (hmmio
== 0) goto errCleanUp
;
420 if (mmioDescend(hmmio
, &ckMainRIFF
, NULL
, 0))
423 TRACE("ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
424 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
, ckMainRIFF
.cksize
);
426 if ((ckMainRIFF
.ckid
!= FOURCC_RIFF
) ||
427 (ckMainRIFF
.fccType
!= mmioFOURCC('W', 'A', 'V', 'E')))
430 mmckInfo
.ckid
= mmioFOURCC('f', 'm', 't', ' ');
431 if (mmioDescend(hmmio
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
))
434 TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
435 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
, mmckInfo
.cksize
);
437 lpWaveFormat
= HeapAlloc(GetProcessHeap(), 0, mmckInfo
.cksize
);
438 if (mmioRead(hmmio
, (HPSTR
)lpWaveFormat
, mmckInfo
.cksize
) < sizeof(WAVEFORMAT
))
441 TRACE("wFormatTag=%04X !\n", lpWaveFormat
->wFormatTag
);
442 TRACE("nChannels=%d \n", lpWaveFormat
->nChannels
);
443 TRACE("nSamplesPerSec=%ld\n", lpWaveFormat
->nSamplesPerSec
);
444 TRACE("nAvgBytesPerSec=%ld\n", lpWaveFormat
->nAvgBytesPerSec
);
445 TRACE("nBlockAlign=%d \n", lpWaveFormat
->nBlockAlign
);
446 TRACE("wBitsPerSample=%u !\n", lpWaveFormat
->wBitsPerSample
);
448 /* move to end of 'fmt ' chunk */
449 mmioAscend(hmmio
, &mmckInfo
, 0);
451 mmckInfo
.ckid
= mmioFOURCC('d', 'a', 't', 'a');
452 if (mmioDescend(hmmio
, &mmckInfo
, &ckMainRIFF
, MMIO_FINDCHUNK
))
455 TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX\n",
456 (LPSTR
)&mmckInfo
.ckid
, (LPSTR
)&mmckInfo
.fccType
, mmckInfo
.cksize
);
458 s
.hEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
460 if (waveOutOpen(&hWave
, WAVE_MAPPER
, lpWaveFormat
, (DWORD
)PlaySound_Callback
,
461 (DWORD
)&s
, CALLBACK_FUNCTION
) != MMSYSERR_NOERROR
)
464 /* make it so that 3 buffers per second are needed */
465 bufsize
= (((lpWaveFormat
->nAvgBytesPerSec
/ 3) - 1) / lpWaveFormat
->nBlockAlign
+ 1) *
466 lpWaveFormat
->nBlockAlign
;
467 waveHdr
= HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WAVEHDR
) + 2 * bufsize
);
468 waveHdr
[0].lpData
= (char*)waveHdr
+ 2 * sizeof(WAVEHDR
);
469 waveHdr
[1].lpData
= (char*)waveHdr
+ 2 * sizeof(WAVEHDR
) + bufsize
;
470 waveHdr
[0].dwUser
= waveHdr
[1].dwUser
= 0L;
471 waveHdr
[0].dwLoops
= waveHdr
[1].dwLoops
= 0L;
472 waveHdr
[0].dwFlags
= waveHdr
[1].dwFlags
= 0L;
473 waveHdr
[0].dwBufferLength
= waveHdr
[1].dwBufferLength
= bufsize
;
474 if (waveOutPrepareHeader(hWave
, &waveHdr
[0], sizeof(WAVEHDR
)) ||
475 waveOutPrepareHeader(hWave
, &waveHdr
[1], sizeof(WAVEHDR
))) {
481 left
= mmckInfo
.cksize
;
482 s
.dwEventCount
= 1L; /* for first buffer */
484 mmioSeek(hmmio
, mmckInfo
.dwDataOffset
, SEEK_SET
);
487 wps
->bStop
= wps
->bLoop
= FALSE
;
490 count
= mmioRead(hmmio
, waveHdr
[index
].lpData
, min(bufsize
, left
));
491 if (count
< 1) break;
493 waveHdr
[index
].dwBufferLength
= count
;
494 waveHdr
[index
].dwFlags
&= ~WHDR_DONE
;
495 if (waveOutWrite(hWave
, &waveHdr
[index
], sizeof(WAVEHDR
)) == MMSYSERR_NOERROR
) {
497 PlaySound_WaitDone(&s
);
499 else FIXME("Couldn't play header\n");
502 } while (wps
->bLoop
);
504 PlaySound_WaitDone(&s
); /* for last buffer */
507 waveOutUnprepareHeader(hWave
, &waveHdr
[0], sizeof(WAVEHDR
));
508 waveOutUnprepareHeader(hWave
, &waveHdr
[1], sizeof(WAVEHDR
));
511 TRACE("Done playing='%s' => %s!\n", debugstr_w(wps
->pszSound
), bRet
? "ok" : "ko");
512 CloseHandle(s
.hEvent
);
513 if (waveHdr
) HeapFree(GetProcessHeap(), 0, waveHdr
);
514 if (lpWaveFormat
) HeapFree(GetProcessHeap(), 0, lpWaveFormat
);
515 if (hWave
) while (waveOutClose(hWave
) == WAVERR_STILLPLAYING
) Sleep(100);
516 if (hmmio
) mmioClose(hmmio
, 0);
518 SetEvent(wps
->hReadyEvent
);
519 iData
->lpPlaySound
= NULL
;
521 if (wps
->bAlloc
) HeapFree(GetProcessHeap(), 0, (void*)wps
->pszSound
);
522 CloseHandle(wps
->hReadyEvent
);
523 HeapFree(GetProcessHeap(), 0, wps
);
528 static BOOL
MULTIMEDIA_IsString(DWORD fdwSound
, const void* psz
)
530 /* SND_RESOURCE is 0x40004 while
531 * SND_MEMORY is 0x00004
533 switch (fdwSound
& (SND_RESOURCE
|SND_ALIAS
|SND_FILENAME
))
535 case SND_RESOURCE
: return HIWORD(psz
) != 0; /* by name or by ID ? */
536 case SND_MEMORY
: return FALSE
;
537 case SND_ALIAS
: /* what about ALIAS_ID ??? */
540 default: FIXME("WTF\n"); return FALSE
;
544 static BOOL
MULTIMEDIA_PlaySound(const void* pszSound
, HMODULE hmod
, DWORD fdwSound
, BOOL bUnicode
)
546 WINE_PLAYSOUND
* wps
= NULL
;
548 LPWINE_MM_IDATA iData
= MULTIMEDIA_GetIData();
551 TRACE("pszSound='%p' hmod=%04X fdwSound=%08lX\n",
552 pszSound
, hmod
, fdwSound
);
554 /* FIXME? I see no difference between SND_NOWAIT and SND_NOSTOP !
555 * there could be one if several sounds can be played at once...
557 if ((fdwSound
& (SND_NOWAIT
| SND_NOSTOP
)) && iData
->lpPlaySound
)
563 /* Trying to stop if playing */
564 EnterCriticalSection(&iData
->cs
);
565 if (iData
->lpPlaySound
) {
566 LPWINE_PLAYSOUND ps2stop
= iData
->lpPlaySound
;
568 hEvt
= ps2stop
->hReadyEvent
;
569 ps2stop
->bStop
= TRUE
;
571 LeaveCriticalSection(&iData
->cs
);
572 /* Waiting playing thread to get ready. I think 10 secs is ok & if not then leave
573 * FIXME: race here (if hEvt is destroyed and reallocated - as a handle - to
574 * another object)... unlikely but possible
576 if (hEvt
) WaitForSingleObject(hEvt
, 1000*10);
578 if (!pszSound
|| (fdwSound
& SND_PURGE
))
579 return TRUE
; /* We stopped playing so leaving */
583 wps
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*wps
));
584 if (!wps
) return FALSE
;
587 wps
->fdwSound
= fdwSound
;
589 if (MULTIMEDIA_IsString(fdwSound
, pszSound
))
593 if (fdwSound
& SND_ASYNC
)
595 wps
->pszSound
= HeapAlloc(GetProcessHeap(), 0, (lstrlenW(pszSound
)+1) * sizeof(WCHAR
));
596 lstrcpyW((LPWSTR
)wps
->pszSound
, pszSound
);
600 wps
->pszSound
= pszSound
;
604 wps
->pszSound
= HEAP_strdupAtoW(GetProcessHeap(), 0, pszSound
);
609 wps
->pszSound
= pszSound
;
610 if ((wps
->hReadyEvent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
)) == 0)
613 } while (InterlockedCompareExchangePointer((void**)&iData
->lpPlaySound
, wps
, NULL
) != NULL
);
615 if (fdwSound
& SND_ASYNC
)
617 wps
->bLoop
= fdwSound
& SND_LOOP
;
618 /* FIXME: memory leak in case of error & cs is still locked */
619 return ((wps
->hThread
= CreateThread(NULL
, 0, proc_PlaySound
, wps
, 0, &id
)) != 0);
622 bRet
= proc_PlaySound(wps
);
627 /**************************************************************************
628 * PlaySoundA [WINMM.@]
630 BOOL WINAPI
PlaySoundA(LPCSTR pszSoundA
, HMODULE hmod
, DWORD fdwSound
)
632 return MULTIMEDIA_PlaySound(pszSoundA
, hmod
, fdwSound
, FALSE
);
635 /**************************************************************************
636 * PlaySoundW [WINMM.@]
638 BOOL WINAPI
PlaySoundW(LPCWSTR pszSoundW
, HMODULE hmod
, DWORD fdwSound
)
640 return MULTIMEDIA_PlaySound(pszSoundW
, hmod
, fdwSound
, TRUE
);
643 /**************************************************************************
644 * PlaySound [MMSYSTEM.3]
646 BOOL16 WINAPI
PlaySound16(LPCSTR pszSound
, HMODULE16 hmod
, DWORD fdwSound
)
651 ReleaseThunkLock(&lc
);
652 retv
= PlaySoundA(pszSound
, hmod
, fdwSound
);
653 RestoreThunkLock(lc
);
658 /**************************************************************************
659 * sndPlaySoundA [WINMM.@]
661 BOOL WINAPI
sndPlaySoundA(LPCSTR pszSoundA
, UINT uFlags
)
663 uFlags
&= ~(SND_ASYNC
|SND_LOOP
|SND_MEMORY
|SND_NODEFAULT
|SND_NOSTOP
|SND_SYNC
);
664 return MULTIMEDIA_PlaySound(pszSoundA
, 0, uFlags
, FALSE
);
667 /**************************************************************************
668 * sndPlaySoundW [WINMM.@]
670 BOOL WINAPI
sndPlaySoundW(LPCWSTR pszSound
, UINT uFlags
)
672 uFlags
&= ~(SND_ASYNC
|SND_LOOP
|SND_MEMORY
|SND_NODEFAULT
|SND_NOSTOP
|SND_SYNC
);
673 return MULTIMEDIA_PlaySound(pszSound
, 0, uFlags
, TRUE
);
676 /**************************************************************************
677 * sndPlaySound [MMSYSTEM.2]
679 BOOL16 WINAPI
sndPlaySound16(LPCSTR lpszSoundName
, UINT16 uFlags
)
684 ReleaseThunkLock(&lc
);
685 retv
= sndPlaySoundA(lpszSoundName
, uFlags
);
686 RestoreThunkLock(lc
);
691 /**************************************************************************
692 * mmsystemGetVersion [MMSYSTEM.5]
693 * return value borrowed from Win95 winmm.dll ;)
695 UINT16 WINAPI
mmsystemGetVersion16(void)
697 return mmsystemGetVersion();
700 /**************************************************************************
701 * mmsystemGetVersion [WINMM.@]
703 UINT WINAPI
mmsystemGetVersion(void)
705 TRACE("3.10 (Win95?)\n");
709 /**************************************************************************
710 * DriverCallback [WINMM.@]
712 BOOL WINAPI
DriverCallback(DWORD dwCallBack
, UINT uFlags
, HDRVR hDev
,
713 UINT wMsg
, DWORD dwUser
, DWORD dwParam1
,
716 TRACE("(%08lX, %04X, %04X, %04X, %08lX, %08lX, %08lX); !\n",
717 dwCallBack
, uFlags
, hDev
, wMsg
, dwUser
, dwParam1
, dwParam2
);
719 switch (uFlags
& DCB_TYPEMASK
) {
723 WARN("uFlags=%04X has null DCB value, but dwCallBack=%08lX is not null !\n", uFlags
, dwCallBack
);
726 TRACE("Window(%04lX) handle=%04X!\n", dwCallBack
, hDev
);
727 PostMessageA((HWND
)dwCallBack
, wMsg
, hDev
, dwParam1
);
729 case DCB_TASK
: /* aka DCB_THREAD */
730 TRACE("Task(%04lx) !\n", dwCallBack
);
731 PostThreadMessageA(dwCallBack
, wMsg
, hDev
, dwParam1
);
734 TRACE("Function (32 bit) !\n");
735 ((LPDRVCALLBACK
)dwCallBack
)(hDev
, wMsg
, dwUser
, dwParam1
, dwParam2
);
738 TRACE("Event(%08lx) !\n", dwCallBack
);
739 SetEvent((HANDLE
)dwCallBack
);
741 case 6: /* I would dub it DCB_MMTHREADSIGNAL */
742 /* this is an undocumented DCB_ value used for mmThreads
743 * loword of dwCallBack contains the handle of the lpMMThd block
744 * which dwSignalCount has to be incremented
747 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(LOWORD(dwCallBack
), 0) );
749 TRACE("mmThread (%04x, %p) !\n", LOWORD(dwCallBack
), lpMMThd
);
750 /* same as mmThreadSignal16 */
751 InterlockedIncrement(&lpMMThd
->dwSignalCount
);
752 SetEvent(lpMMThd
->hEvent
);
753 /* some other stuff on lpMMThd->hVxD */
758 /* this is an undocumented DCB_ value for... I don't know */
762 WARN("Unknown callback type %d\n", uFlags
& DCB_TYPEMASK
);
769 /**************************************************************************
770 * DriverCallback [MMSYSTEM.31]
772 BOOL16 WINAPI
DriverCallback16(DWORD dwCallBack
, UINT16 uFlags
, HDRVR16 hDev
,
773 WORD wMsg
, DWORD dwUser
, DWORD dwParam1
,
776 return DriverCallback(dwCallBack
, uFlags
, hDev
, wMsg
, dwUser
, dwParam1
, dwParam2
);
779 /**************************************************************************
780 * Mixer devices. New to Win95
783 /**************************************************************************
784 * find out the real mixer ID depending on hmix (depends on dwFlags)
786 static LPWINE_MIXER
MIXER_GetDev(HMIXEROBJ hmix
, DWORD dwFlags
)
788 LPWINE_MIXER lpwm
= NULL
;
790 switch (dwFlags
& 0xF0000000ul
) {
791 case MIXER_OBJECTF_MIXER
:
792 lpwm
= (LPWINE_MIXER
)MMDRV_Get(hmix
, MMDRV_MIXER
, TRUE
);
794 case MIXER_OBJECTF_HMIXER
:
795 lpwm
= (LPWINE_MIXER
)MMDRV_Get(hmix
, MMDRV_MIXER
, FALSE
);
797 case MIXER_OBJECTF_WAVEOUT
:
798 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEOUT
, TRUE
, MMDRV_MIXER
);
800 case MIXER_OBJECTF_HWAVEOUT
:
801 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEOUT
, FALSE
, MMDRV_MIXER
);
803 case MIXER_OBJECTF_WAVEIN
:
804 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEIN
, TRUE
, MMDRV_MIXER
);
806 case MIXER_OBJECTF_HWAVEIN
:
807 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_WAVEIN
, FALSE
, MMDRV_MIXER
);
809 case MIXER_OBJECTF_MIDIOUT
:
810 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIOUT
, TRUE
, MMDRV_MIXER
);
812 case MIXER_OBJECTF_HMIDIOUT
:
813 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIOUT
, FALSE
, MMDRV_MIXER
);
815 case MIXER_OBJECTF_MIDIIN
:
816 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIIN
, TRUE
, MMDRV_MIXER
);
818 case MIXER_OBJECTF_HMIDIIN
:
819 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_MIDIIN
, FALSE
, MMDRV_MIXER
);
821 case MIXER_OBJECTF_AUX
:
822 lpwm
= (LPWINE_MIXER
)MMDRV_GetRelated(hmix
, MMDRV_AUX
, TRUE
, MMDRV_MIXER
);
825 FIXME("Unsupported flag (%08lx)\n", dwFlags
& 0xF0000000ul
);
831 /**************************************************************************
832 * mixerGetNumDevs [WINMM.@]
834 UINT WINAPI
mixerGetNumDevs(void)
836 return MMDRV_GetNum(MMDRV_MIXER
);
839 /**************************************************************************
840 * mixerGetNumDevs [MMSYSTEM.800]
842 UINT16 WINAPI
mixerGetNumDevs16(void)
844 return MMDRV_GetNum(MMDRV_MIXER
);
847 /**************************************************************************
848 * mixerGetDevCapsA [WINMM.@]
850 UINT WINAPI
mixerGetDevCapsA(UINT devid
, LPMIXERCAPSA mixcaps
, UINT size
)
854 if ((wmld
= MMDRV_Get(devid
, MMDRV_MIXER
, TRUE
)) == NULL
)
855 return MMSYSERR_BADDEVICEID
;
857 return MMDRV_Message(wmld
, MXDM_GETDEVCAPS
, (DWORD
)mixcaps
, size
, TRUE
);
860 /**************************************************************************
861 * mixerGetDevCapsW [WINMM.@]
863 UINT WINAPI
mixerGetDevCapsW(UINT devid
, LPMIXERCAPSW mixcaps
, UINT size
)
866 UINT ret
= mixerGetDevCapsA(devid
, &micA
, sizeof(micA
));
868 if (ret
== MMSYSERR_NOERROR
) {
869 mixcaps
->wMid
= micA
.wMid
;
870 mixcaps
->wPid
= micA
.wPid
;
871 mixcaps
->vDriverVersion
= micA
.vDriverVersion
;
872 MultiByteToWideChar( CP_ACP
, 0, micA
.szPname
, -1, mixcaps
->szPname
,
873 sizeof(mixcaps
->szPname
)/sizeof(WCHAR
) );
874 mixcaps
->fdwSupport
= micA
.fdwSupport
;
875 mixcaps
->cDestinations
= micA
.cDestinations
;
880 /**************************************************************************
881 * mixerGetDevCaps [MMSYSTEM.801]
883 UINT16 WINAPI
mixerGetDevCaps16(UINT16 devid
, LPMIXERCAPS16 mixcaps
,
887 UINT ret
= mixerGetDevCapsA(devid
, &micA
, sizeof(micA
));
889 if (ret
== MMSYSERR_NOERROR
) {
890 mixcaps
->wMid
= micA
.wMid
;
891 mixcaps
->wPid
= micA
.wPid
;
892 mixcaps
->vDriverVersion
= micA
.vDriverVersion
;
893 strcpy(mixcaps
->szPname
, micA
.szPname
);
894 mixcaps
->fdwSupport
= micA
.fdwSupport
;
895 mixcaps
->cDestinations
= micA
.cDestinations
;
900 static UINT
MMSYSTEM_mixerOpen(LPHMIXER lphMix
, UINT uDeviceID
, DWORD dwCallback
,
901 DWORD dwInstance
, DWORD fdwOpen
, BOOL bFrom32
)
908 TRACE("(%p, %d, %08lx, %08lx, %08lx)\n",
909 lphMix
, uDeviceID
, dwCallback
, dwInstance
, fdwOpen
);
911 wmld
= MMDRV_Alloc(sizeof(WINE_MIXER
), MMDRV_MIXER
, &hMix
, &fdwOpen
,
912 &dwCallback
, &dwInstance
, bFrom32
);
914 wmld
->uDeviceID
= uDeviceID
;
916 mod
.dwCallback
= dwCallback
;
917 mod
.dwInstance
= dwInstance
;
919 dwRet
= MMDRV_Open(wmld
, MXDM_OPEN
, (DWORD
)&mod
, fdwOpen
);
921 if (dwRet
!= MMSYSERR_NOERROR
) {
922 MMDRV_Free(hMix
, wmld
);
925 if (lphMix
) *lphMix
= hMix
;
926 TRACE("=> %ld hMixer=%04x\n", dwRet
, hMix
);
931 /**************************************************************************
932 * mixerOpen [WINMM.@]
934 UINT WINAPI
mixerOpen(LPHMIXER lphMix
, UINT uDeviceID
, DWORD dwCallback
,
935 DWORD dwInstance
, DWORD fdwOpen
)
937 return MMSYSTEM_mixerOpen(lphMix
, uDeviceID
,
938 dwCallback
, dwInstance
, fdwOpen
, TRUE
);
941 /**************************************************************************
942 * mixerOpen [MMSYSTEM.802]
944 UINT16 WINAPI
mixerOpen16(LPHMIXER16 lphmix
, UINT16 uDeviceID
, DWORD dwCallback
,
945 DWORD dwInstance
, DWORD fdwOpen
)
950 ret
= MMSYSTEM_mixerOpen(&hmix
, uDeviceID
,
951 dwCallback
, dwInstance
, fdwOpen
, FALSE
);
952 if (lphmix
) *lphmix
= hmix
;
956 /**************************************************************************
957 * mixerClose [WINMM.@]
959 UINT WINAPI
mixerClose(HMIXER hMix
)
964 TRACE("(%04x)\n", hMix
);
966 if ((wmld
= MMDRV_Get(hMix
, MMDRV_MIXER
, FALSE
)) == NULL
) return MMSYSERR_INVALHANDLE
;
968 dwRet
= MMDRV_Close(wmld
, MXDM_CLOSE
);
969 MMDRV_Free(hMix
, wmld
);
974 /**************************************************************************
975 * mixerClose [MMSYSTEM.803]
977 UINT16 WINAPI
mixerClose16(HMIXER16 hMix
)
979 return mixerClose(hMix
);
982 /**************************************************************************
983 * mixerGetID [WINMM.@]
985 UINT WINAPI
mixerGetID(HMIXEROBJ hmix
, LPUINT lpid
, DWORD fdwID
)
989 TRACE("(%04x %p %08lx)\n", hmix
, lpid
, fdwID
);
991 if ((lpwm
= MIXER_GetDev(hmix
, fdwID
)) == NULL
) {
992 return MMSYSERR_INVALHANDLE
;
996 *lpid
= lpwm
->mld
.uDeviceID
;
998 return MMSYSERR_NOERROR
;
1001 /**************************************************************************
1002 * mixerGetID (MMSYSTEM.806)
1004 UINT16 WINAPI
mixerGetID16(HMIXEROBJ16 hmix
, LPUINT16 lpid
, DWORD fdwID
)
1007 UINT ret
= mixerGetID(hmix
, &xid
, fdwID
);
1014 /**************************************************************************
1015 * mixerGetControlDetailsA [WINMM.@]
1017 UINT WINAPI
mixerGetControlDetailsA(HMIXEROBJ hmix
, LPMIXERCONTROLDETAILS lpmcdA
,
1022 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcdA
, fdwDetails
);
1024 if ((lpwm
= MIXER_GetDev(hmix
, fdwDetails
)) == NULL
)
1025 return MMSYSERR_INVALHANDLE
;
1027 if (lpmcdA
== NULL
|| lpmcdA
->cbStruct
!= sizeof(*lpmcdA
))
1028 return MMSYSERR_INVALPARAM
;
1030 return MMDRV_Message(&lpwm
->mld
, MXDM_GETCONTROLDETAILS
, (DWORD
)lpmcdA
,
1034 /**************************************************************************
1035 * mixerGetControlDetailsW [WINMM.@]
1037 UINT WINAPI
mixerGetControlDetailsW(HMIXEROBJ hmix
, LPMIXERCONTROLDETAILS lpmcd
, DWORD fdwDetails
)
1039 DWORD ret
= MMSYSERR_NOTENABLED
;
1041 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcd
, fdwDetails
);
1043 if (lpmcd
== NULL
|| lpmcd
->cbStruct
!= sizeof(*lpmcd
))
1044 return MMSYSERR_INVALPARAM
;
1046 switch (fdwDetails
& MIXER_GETCONTROLDETAILSF_QUERYMASK
) {
1047 case MIXER_GETCONTROLDETAILSF_VALUE
:
1048 /* can savely use W structure as it is, no string inside */
1049 ret
= mixerGetControlDetailsA(hmix
, lpmcd
, fdwDetails
);
1051 case MIXER_GETCONTROLDETAILSF_LISTTEXT
:
1053 MIXERCONTROLDETAILS_LISTTEXTW
*pDetailsW
= (MIXERCONTROLDETAILS_LISTTEXTW
*)lpmcd
->paDetails
;
1054 MIXERCONTROLDETAILS_LISTTEXTA
*pDetailsA
;
1055 int size
= max(1, lpmcd
->cChannels
) * sizeof(MIXERCONTROLDETAILS_LISTTEXTA
);
1058 if (lpmcd
->u
.cMultipleItems
!= 0) {
1059 size
*= lpmcd
->u
.cMultipleItems
;
1061 pDetailsA
= (MIXERCONTROLDETAILS_LISTTEXTA
*)HeapAlloc(GetProcessHeap(), 0, size
);
1062 lpmcd
->paDetails
= pDetailsA
;
1063 lpmcd
->cbDetails
= sizeof(MIXERCONTROLDETAILS_LISTTEXTA
);
1064 /* set up lpmcd->paDetails */
1065 ret
= mixerGetControlDetailsA(hmix
, lpmcd
, fdwDetails
);
1066 /* copy from lpmcd->paDetails back to paDetailsW; */
1067 if(ret
== MMSYSERR_NOERROR
) {
1068 for(i
=0;i
<lpmcd
->u
.cMultipleItems
*lpmcd
->cChannels
;i
++) {
1069 pDetailsW
->dwParam1
= pDetailsA
->dwParam1
;
1070 pDetailsW
->dwParam2
= pDetailsA
->dwParam2
;
1071 MultiByteToWideChar( CP_ACP
, 0, pDetailsA
->szName
, -1,
1073 sizeof(pDetailsW
->szName
)/sizeof(WCHAR
) );
1077 pDetailsA
-= lpmcd
->u
.cMultipleItems
*lpmcd
->cChannels
;
1078 pDetailsW
-= lpmcd
->u
.cMultipleItems
*lpmcd
->cChannels
;
1080 HeapFree(GetProcessHeap(), 0, pDetailsA
);
1081 lpmcd
->paDetails
= pDetailsW
;
1082 lpmcd
->cbDetails
= sizeof(MIXERCONTROLDETAILS_LISTTEXTW
);
1086 ERR("Unsupported fdwDetails=0x%08lx\n", fdwDetails
);
1092 /**************************************************************************
1093 * mixerGetControlDetails [MMSYSTEM.808]
1095 UINT16 WINAPI
mixerGetControlDetails16(HMIXEROBJ16 hmix
,
1096 LPMIXERCONTROLDETAILS16 lpmcd
,
1099 DWORD ret
= MMSYSERR_NOTENABLED
;
1102 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcd
, fdwDetails
);
1104 if (lpmcd
== NULL
|| lpmcd
->cbStruct
!= sizeof(*lpmcd
))
1105 return MMSYSERR_INVALPARAM
;
1107 sppaDetails
= (SEGPTR
)lpmcd
->paDetails
;
1108 lpmcd
->paDetails
= MapSL(sppaDetails
);
1109 ret
= mixerGetControlDetailsA(hmix
, (LPMIXERCONTROLDETAILS
)lpmcd
, fdwDetails
);
1110 lpmcd
->paDetails
= (LPVOID
)sppaDetails
;
1115 /**************************************************************************
1116 * mixerGetLineControlsA [WINMM.@]
1118 UINT WINAPI
mixerGetLineControlsA(HMIXEROBJ hmix
, LPMIXERLINECONTROLSA lpmlcA
,
1123 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmlcA
, fdwControls
);
1125 if ((lpwm
= MIXER_GetDev(hmix
, fdwControls
)) == NULL
)
1126 return MMSYSERR_INVALHANDLE
;
1128 if (lpmlcA
== NULL
|| lpmlcA
->cbStruct
!= sizeof(*lpmlcA
))
1129 return MMSYSERR_INVALPARAM
;
1131 return MMDRV_Message(&lpwm
->mld
, MXDM_GETLINECONTROLS
, (DWORD
)lpmlcA
,
1135 /**************************************************************************
1136 * mixerGetLineControlsW [WINMM.@]
1138 UINT WINAPI
mixerGetLineControlsW(HMIXEROBJ hmix
, LPMIXERLINECONTROLSW lpmlcW
,
1141 MIXERLINECONTROLSA mlcA
;
1145 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmlcW
, fdwControls
);
1147 if (lpmlcW
== NULL
|| lpmlcW
->cbStruct
!= sizeof(*lpmlcW
) ||
1148 lpmlcW
->cbmxctrl
!= sizeof(MIXERCONTROLW
))
1149 return MMSYSERR_INVALPARAM
;
1151 mlcA
.cbStruct
= sizeof(mlcA
);
1152 mlcA
.dwLineID
= lpmlcW
->dwLineID
;
1153 mlcA
.u
.dwControlID
= lpmlcW
->u
.dwControlID
;
1154 mlcA
.u
.dwControlType
= lpmlcW
->u
.dwControlType
;
1155 mlcA
.cControls
= lpmlcW
->cControls
;
1156 mlcA
.cbmxctrl
= sizeof(MIXERCONTROLA
);
1157 mlcA
.pamxctrl
= HeapAlloc(GetProcessHeap(), 0,
1158 mlcA
.cControls
* mlcA
.cbmxctrl
);
1160 ret
= mixerGetLineControlsA(hmix
, &mlcA
, fdwControls
);
1162 if (ret
== MMSYSERR_NOERROR
) {
1163 lpmlcW
->dwLineID
= mlcA
.dwLineID
;
1164 lpmlcW
->u
.dwControlID
= mlcA
.u
.dwControlID
;
1165 lpmlcW
->u
.dwControlType
= mlcA
.u
.dwControlType
;
1166 lpmlcW
->cControls
= mlcA
.cControls
;
1168 for (i
= 0; i
< mlcA
.cControls
; i
++) {
1169 lpmlcW
->pamxctrl
[i
].cbStruct
= sizeof(MIXERCONTROLW
);
1170 lpmlcW
->pamxctrl
[i
].dwControlID
= mlcA
.pamxctrl
[i
].dwControlID
;
1171 lpmlcW
->pamxctrl
[i
].dwControlType
= mlcA
.pamxctrl
[i
].dwControlType
;
1172 lpmlcW
->pamxctrl
[i
].fdwControl
= mlcA
.pamxctrl
[i
].fdwControl
;
1173 lpmlcW
->pamxctrl
[i
].cMultipleItems
= mlcA
.pamxctrl
[i
].cMultipleItems
;
1174 MultiByteToWideChar( CP_ACP
, 0, mlcA
.pamxctrl
[i
].szShortName
, -1,
1175 lpmlcW
->pamxctrl
[i
].szShortName
,
1176 sizeof(lpmlcW
->pamxctrl
[i
].szShortName
)/sizeof(WCHAR
) );
1177 MultiByteToWideChar( CP_ACP
, 0, mlcA
.pamxctrl
[i
].szName
, -1,
1178 lpmlcW
->pamxctrl
[i
].szName
,
1179 sizeof(lpmlcW
->pamxctrl
[i
].szName
)/sizeof(WCHAR
) );
1180 /* sizeof(lpmlcW->pamxctrl[i].Bounds) ==
1181 * sizeof(mlcA.pamxctrl[i].Bounds) */
1182 memcpy(&lpmlcW
->pamxctrl
[i
].Bounds
, &mlcA
.pamxctrl
[i
].Bounds
,
1183 sizeof(mlcA
.pamxctrl
[i
].Bounds
));
1184 /* sizeof(lpmlcW->pamxctrl[i].Metrics) ==
1185 * sizeof(mlcA.pamxctrl[i].Metrics) */
1186 memcpy(&lpmlcW
->pamxctrl
[i
].Metrics
, &mlcA
.pamxctrl
[i
].Metrics
,
1187 sizeof(mlcA
.pamxctrl
[i
].Metrics
));
1191 HeapFree(GetProcessHeap(), 0, mlcA
.pamxctrl
);
1196 /**************************************************************************
1197 * mixerGetLineControls [MMSYSTEM.807]
1199 UINT16 WINAPI
mixerGetLineControls16(HMIXEROBJ16 hmix
,
1200 LPMIXERLINECONTROLS16 lpmlc16
,
1203 MIXERLINECONTROLSA mlcA
;
1206 LPMIXERCONTROL16 lpmc16
;
1208 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmlc16
, fdwControls
);
1210 if (lpmlc16
== NULL
|| lpmlc16
->cbStruct
!= sizeof(*lpmlc16
) ||
1211 lpmlc16
->cbmxctrl
!= sizeof(MIXERCONTROL16
))
1212 return MMSYSERR_INVALPARAM
;
1214 mlcA
.cbStruct
= sizeof(mlcA
);
1215 mlcA
.dwLineID
= lpmlc16
->dwLineID
;
1216 mlcA
.u
.dwControlID
= lpmlc16
->u
.dwControlID
;
1217 mlcA
.u
.dwControlType
= lpmlc16
->u
.dwControlType
;
1218 mlcA
.cControls
= lpmlc16
->cControls
;
1219 mlcA
.cbmxctrl
= sizeof(MIXERCONTROLA
);
1220 mlcA
.pamxctrl
= HeapAlloc(GetProcessHeap(), 0,
1221 mlcA
.cControls
* mlcA
.cbmxctrl
);
1223 ret
= mixerGetLineControlsA(hmix
, &mlcA
, fdwControls
);
1225 if (ret
== MMSYSERR_NOERROR
) {
1226 lpmlc16
->dwLineID
= mlcA
.dwLineID
;
1227 lpmlc16
->u
.dwControlID
= mlcA
.u
.dwControlID
;
1228 lpmlc16
->u
.dwControlType
= mlcA
.u
.dwControlType
;
1229 lpmlc16
->cControls
= mlcA
.cControls
;
1231 lpmc16
= MapSL(lpmlc16
->pamxctrl
);
1233 for (i
= 0; i
< mlcA
.cControls
; i
++) {
1234 lpmc16
[i
].cbStruct
= sizeof(MIXERCONTROL16
);
1235 lpmc16
[i
].dwControlID
= mlcA
.pamxctrl
[i
].dwControlID
;
1236 lpmc16
[i
].dwControlType
= mlcA
.pamxctrl
[i
].dwControlType
;
1237 lpmc16
[i
].fdwControl
= mlcA
.pamxctrl
[i
].fdwControl
;
1238 lpmc16
[i
].cMultipleItems
= mlcA
.pamxctrl
[i
].cMultipleItems
;
1239 strcpy(lpmc16
[i
].szShortName
, mlcA
.pamxctrl
[i
].szShortName
);
1240 strcpy(lpmc16
[i
].szName
, mlcA
.pamxctrl
[i
].szName
);
1241 /* sizeof(lpmc16[i].Bounds) == sizeof(mlcA.pamxctrl[i].Bounds) */
1242 memcpy(&lpmc16
[i
].Bounds
, &mlcA
.pamxctrl
[i
].Bounds
,
1243 sizeof(mlcA
.pamxctrl
[i
].Bounds
));
1244 /* sizeof(lpmc16[i].Metrics) == sizeof(mlcA.pamxctrl[i].Metrics) */
1245 memcpy(&lpmc16
[i
].Metrics
, &mlcA
.pamxctrl
[i
].Metrics
,
1246 sizeof(mlcA
.pamxctrl
[i
].Metrics
));
1250 HeapFree(GetProcessHeap(), 0, mlcA
.pamxctrl
);
1255 /**************************************************************************
1256 * mixerGetLineInfoA [WINMM.@]
1258 UINT WINAPI
mixerGetLineInfoA(HMIXEROBJ hmix
, LPMIXERLINEA lpmliW
, DWORD fdwInfo
)
1262 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmliW
, fdwInfo
);
1264 if ((lpwm
= MIXER_GetDev(hmix
, fdwInfo
)) == NULL
)
1265 return MMSYSERR_INVALHANDLE
;
1267 return MMDRV_Message(&lpwm
->mld
, MXDM_GETLINEINFO
, (DWORD
)lpmliW
,
1271 /**************************************************************************
1272 * mixerGetLineInfoW [WINMM.@]
1274 UINT WINAPI
mixerGetLineInfoW(HMIXEROBJ hmix
, LPMIXERLINEW lpmliW
,
1280 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmliW
, fdwInfo
);
1282 if (lpmliW
== NULL
|| lpmliW
->cbStruct
!= sizeof(*lpmliW
))
1283 return MMSYSERR_INVALPARAM
;
1285 mliA
.cbStruct
= sizeof(mliA
);
1286 switch (fdwInfo
& MIXER_GETLINEINFOF_QUERYMASK
) {
1287 case MIXER_GETLINEINFOF_COMPONENTTYPE
:
1288 mliA
.dwComponentType
= lpmliW
->dwComponentType
;
1290 case MIXER_GETLINEINFOF_DESTINATION
:
1291 mliA
.dwDestination
= lpmliW
->dwDestination
;
1293 case MIXER_GETLINEINFOF_LINEID
:
1294 mliA
.dwLineID
= lpmliW
->dwLineID
;
1296 case MIXER_GETLINEINFOF_SOURCE
:
1297 mliA
.dwDestination
= lpmliW
->dwDestination
;
1298 mliA
.dwSource
= lpmliW
->dwSource
;
1300 case MIXER_GETLINEINFOF_TARGETTYPE
:
1301 mliA
.Target
.dwType
= lpmliW
->Target
.dwType
;
1302 mliA
.Target
.wMid
= lpmliW
->Target
.wMid
;
1303 mliA
.Target
.wPid
= lpmliW
->Target
.wPid
;
1304 mliA
.Target
.vDriverVersion
= lpmliW
->Target
.vDriverVersion
;
1305 WideCharToMultiByte( CP_ACP
, 0, lpmliW
->Target
.szPname
, -1, mliA
.Target
.szPname
, sizeof(mliA
.Target
.szPname
), NULL
, NULL
);
1308 FIXME("Unsupported fdwControls=0x%08lx\n", fdwInfo
);
1311 ret
= mixerGetLineInfoA(hmix
, &mliA
, fdwInfo
);
1313 lpmliW
->dwDestination
= mliA
.dwDestination
;
1314 lpmliW
->dwSource
= mliA
.dwSource
;
1315 lpmliW
->dwLineID
= mliA
.dwLineID
;
1316 lpmliW
->fdwLine
= mliA
.fdwLine
;
1317 lpmliW
->dwUser
= mliA
.dwUser
;
1318 lpmliW
->dwComponentType
= mliA
.dwComponentType
;
1319 lpmliW
->cChannels
= mliA
.cChannels
;
1320 lpmliW
->cConnections
= mliA
.cConnections
;
1321 lpmliW
->cControls
= mliA
.cControls
;
1322 MultiByteToWideChar( CP_ACP
, 0, mliA
.szShortName
, -1, lpmliW
->szShortName
,
1323 sizeof(lpmliW
->szShortName
)/sizeof(WCHAR
) );
1324 MultiByteToWideChar( CP_ACP
, 0, mliA
.szName
, -1, lpmliW
->szName
,
1325 sizeof(lpmliW
->szName
)/sizeof(WCHAR
) );
1326 lpmliW
->Target
.dwType
= mliA
.Target
.dwType
;
1327 lpmliW
->Target
.dwDeviceID
= mliA
.Target
.dwDeviceID
;
1328 lpmliW
->Target
.wMid
= mliA
.Target
.wMid
;
1329 lpmliW
->Target
.wPid
= mliA
.Target
.wPid
;
1330 lpmliW
->Target
.vDriverVersion
= mliA
.Target
.vDriverVersion
;
1331 MultiByteToWideChar( CP_ACP
, 0, mliA
.Target
.szPname
, -1, lpmliW
->Target
.szPname
,
1332 sizeof(lpmliW
->Target
.szPname
)/sizeof(WCHAR
) );
1337 /**************************************************************************
1338 * mixerGetLineInfo [MMSYSTEM.805]
1340 UINT16 WINAPI
mixerGetLineInfo16(HMIXEROBJ16 hmix
, LPMIXERLINE16 lpmli16
,
1346 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmli16
, fdwInfo
);
1348 if (lpmli16
== NULL
|| lpmli16
->cbStruct
!= sizeof(*lpmli16
))
1349 return MMSYSERR_INVALPARAM
;
1351 mliA
.cbStruct
= sizeof(mliA
);
1352 switch (fdwInfo
& MIXER_GETLINEINFOF_QUERYMASK
) {
1353 case MIXER_GETLINEINFOF_COMPONENTTYPE
:
1354 mliA
.dwComponentType
= lpmli16
->dwComponentType
;
1356 case MIXER_GETLINEINFOF_DESTINATION
:
1357 mliA
.dwDestination
= lpmli16
->dwDestination
;
1359 case MIXER_GETLINEINFOF_LINEID
:
1360 mliA
.dwLineID
= lpmli16
->dwLineID
;
1362 case MIXER_GETLINEINFOF_SOURCE
:
1363 mliA
.dwDestination
= lpmli16
->dwDestination
;
1364 mliA
.dwSource
= lpmli16
->dwSource
;
1366 case MIXER_GETLINEINFOF_TARGETTYPE
:
1367 mliA
.Target
.dwType
= lpmli16
->Target
.dwType
;
1368 mliA
.Target
.wMid
= lpmli16
->Target
.wMid
;
1369 mliA
.Target
.wPid
= lpmli16
->Target
.wPid
;
1370 mliA
.Target
.vDriverVersion
= lpmli16
->Target
.vDriverVersion
;
1371 strcpy(mliA
.Target
.szPname
, lpmli16
->Target
.szPname
);
1374 FIXME("Unsupported fdwControls=0x%08lx\n", fdwInfo
);
1377 ret
= mixerGetLineInfoA(hmix
, &mliA
, fdwInfo
);
1379 lpmli16
->dwDestination
= mliA
.dwDestination
;
1380 lpmli16
->dwSource
= mliA
.dwSource
;
1381 lpmli16
->dwLineID
= mliA
.dwLineID
;
1382 lpmli16
->fdwLine
= mliA
.fdwLine
;
1383 lpmli16
->dwUser
= mliA
.dwUser
;
1384 lpmli16
->dwComponentType
= mliA
.dwComponentType
;
1385 lpmli16
->cChannels
= mliA
.cChannels
;
1386 lpmli16
->cConnections
= mliA
.cConnections
;
1387 lpmli16
->cControls
= mliA
.cControls
;
1388 strcpy(lpmli16
->szShortName
, mliA
.szShortName
);
1389 strcpy(lpmli16
->szName
, mliA
.szName
);
1390 lpmli16
->Target
.dwType
= mliA
.Target
.dwType
;
1391 lpmli16
->Target
.dwDeviceID
= mliA
.Target
.dwDeviceID
;
1392 lpmli16
->Target
.wMid
= mliA
.Target
.wMid
;
1393 lpmli16
->Target
.wPid
= mliA
.Target
.wPid
;
1394 lpmli16
->Target
.vDriverVersion
= mliA
.Target
.vDriverVersion
;
1395 strcpy(lpmli16
->Target
.szPname
, mliA
.Target
.szPname
);
1400 /**************************************************************************
1401 * mixerSetControlDetails [WINMM.@]
1403 UINT WINAPI
mixerSetControlDetails(HMIXEROBJ hmix
, LPMIXERCONTROLDETAILS lpmcdA
,
1408 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcdA
, fdwDetails
);
1410 if ((lpwm
= MIXER_GetDev(hmix
, fdwDetails
)) == NULL
)
1411 return MMSYSERR_INVALHANDLE
;
1413 return MMDRV_Message(&lpwm
->mld
, MXDM_SETCONTROLDETAILS
, (DWORD
)lpmcdA
,
1417 /**************************************************************************
1418 * mixerSetControlDetails [MMSYSTEM.809]
1420 UINT16 WINAPI
mixerSetControlDetails16(HMIXEROBJ16 hmix
,
1421 LPMIXERCONTROLDETAILS16 lpmcd
,
1424 TRACE("(%04x, %p, %08lx)\n", hmix
, lpmcd
, fdwDetails
);
1425 return MMSYSERR_NOTENABLED
;
1428 /**************************************************************************
1429 * mixerMessage [WINMM.@]
1431 UINT WINAPI
mixerMessage(HMIXER hmix
, UINT uMsg
, DWORD dwParam1
, DWORD dwParam2
)
1435 TRACE("(%04lx, %d, %08lx, %08lx): semi-stub?\n",
1436 (DWORD
)hmix
, uMsg
, dwParam1
, dwParam2
);
1438 if ((wmld
= MMDRV_Get(hmix
, MMDRV_MIXER
, FALSE
)) == NULL
)
1439 return MMSYSERR_INVALHANDLE
;
1441 return MMDRV_Message(wmld
, uMsg
, dwParam1
, dwParam2
, TRUE
);
1444 /**************************************************************************
1445 * mixerMessage [MMSYSTEM.804]
1447 DWORD WINAPI
mixerMessage16(HMIXER16 hmix
, UINT16 uMsg
, DWORD dwParam1
,
1450 return mixerMessage(hmix
, uMsg
, dwParam1
, dwParam2
);
1453 /**************************************************************************
1454 * auxGetNumDevs [WINMM.@]
1456 UINT WINAPI
auxGetNumDevs(void)
1458 return MMDRV_GetNum(MMDRV_AUX
);
1461 /**************************************************************************
1462 * auxGetNumDevs [MMSYSTEM.350]
1464 UINT16 WINAPI
auxGetNumDevs16(void)
1466 return MMDRV_GetNum(MMDRV_AUX
);
1469 /**************************************************************************
1470 * auxGetDevCapsW [WINMM.@]
1472 UINT WINAPI
auxGetDevCapsW(UINT uDeviceID
, LPAUXCAPSW lpCaps
, UINT uSize
)
1475 UINT ret
= auxGetDevCapsA(uDeviceID
, &acA
, sizeof(acA
));
1477 lpCaps
->wMid
= acA
.wMid
;
1478 lpCaps
->wPid
= acA
.wPid
;
1479 lpCaps
->vDriverVersion
= acA
.vDriverVersion
;
1480 MultiByteToWideChar( CP_ACP
, 0, acA
.szPname
, -1, lpCaps
->szPname
,
1481 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
1482 lpCaps
->wTechnology
= acA
.wTechnology
;
1483 lpCaps
->dwSupport
= acA
.dwSupport
;
1487 /**************************************************************************
1488 * auxGetDevCapsA [WINMM.@]
1490 UINT WINAPI
auxGetDevCapsA(UINT uDeviceID
, LPAUXCAPSA lpCaps
, UINT uSize
)
1494 TRACE("(%04X, %p, %d) !\n", uDeviceID
, lpCaps
, uSize
);
1496 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1497 return MMSYSERR_INVALHANDLE
;
1498 return MMDRV_Message(wmld
, AUXDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
1501 /**************************************************************************
1502 * auxGetDevCaps [MMSYSTEM.351]
1504 UINT16 WINAPI
auxGetDevCaps16(UINT16 uDeviceID
, LPAUXCAPS16 lpCaps
, UINT16 uSize
)
1508 TRACE("(%04X, %p, %d) !\n", uDeviceID
, lpCaps
, uSize
);
1510 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1511 return MMSYSERR_INVALHANDLE
;
1512 return MMDRV_Message(wmld
, AUXDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
1515 /**************************************************************************
1516 * auxGetVolume [WINMM.@]
1518 UINT WINAPI
auxGetVolume(UINT uDeviceID
, DWORD
* lpdwVolume
)
1522 TRACE("(%04X, %p) !\n", uDeviceID
, lpdwVolume
);
1524 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1525 return MMSYSERR_INVALHANDLE
;
1526 return MMDRV_Message(wmld
, AUXDM_GETVOLUME
, (DWORD
)lpdwVolume
, 0L, TRUE
);
1529 /**************************************************************************
1530 * auxGetVolume [MMSYSTEM.352]
1532 UINT16 WINAPI
auxGetVolume16(UINT16 uDeviceID
, LPDWORD lpdwVolume
)
1536 TRACE("(%04X, %p) !\n", uDeviceID
, lpdwVolume
);
1538 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1539 return MMSYSERR_INVALHANDLE
;
1540 return MMDRV_Message(wmld
, AUXDM_GETVOLUME
, (DWORD
)lpdwVolume
, 0L, TRUE
);
1543 /**************************************************************************
1544 * auxSetVolume [WINMM.@]
1546 UINT WINAPI
auxSetVolume(UINT uDeviceID
, DWORD dwVolume
)
1550 TRACE("(%04X, %lu) !\n", uDeviceID
, dwVolume
);
1552 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1553 return MMSYSERR_INVALHANDLE
;
1554 return MMDRV_Message(wmld
, AUXDM_SETVOLUME
, dwVolume
, 0L, TRUE
);
1557 /**************************************************************************
1558 * auxSetVolume [MMSYSTEM.353]
1560 UINT16 WINAPI
auxSetVolume16(UINT16 uDeviceID
, DWORD dwVolume
)
1564 TRACE("(%04X, %lu) !\n", uDeviceID
, dwVolume
);
1566 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1567 return MMSYSERR_INVALHANDLE
;
1568 return MMDRV_Message(wmld
, AUXDM_SETVOLUME
, dwVolume
, 0L, TRUE
);
1571 /**************************************************************************
1572 * auxOutMessage [WINMM.@]
1574 DWORD WINAPI
auxOutMessage(UINT uDeviceID
, UINT uMessage
, DWORD dw1
, DWORD dw2
)
1578 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1579 return MMSYSERR_INVALHANDLE
;
1581 return MMDRV_Message(wmld
, uMessage
, dw1
, dw2
, TRUE
);
1584 /**************************************************************************
1585 * auxOutMessage [MMSYSTEM.354]
1587 DWORD WINAPI
auxOutMessage16(UINT16 uDeviceID
, UINT16 uMessage
, DWORD dw1
, DWORD dw2
)
1591 TRACE("(%04X, %04X, %08lX, %08lX)\n", uDeviceID
, uMessage
, dw1
, dw2
);
1594 case AUXDM_GETNUMDEVS
:
1595 case AUXDM_SETVOLUME
:
1596 /* no argument conversion needed */
1598 case AUXDM_GETVOLUME
:
1599 return auxGetVolume16(uDeviceID
, MapSL(dw1
));
1600 case AUXDM_GETDEVCAPS
:
1601 return auxGetDevCaps16(uDeviceID
, MapSL(dw1
), dw2
);
1603 TRACE("(%04x, %04x, %08lx, %08lx): unhandled message\n",
1604 uDeviceID
, uMessage
, dw1
, dw2
);
1607 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_AUX
, TRUE
)) == NULL
)
1608 return MMSYSERR_INVALHANDLE
;
1610 return MMDRV_Message(wmld
, uMessage
, dw1
, dw2
, TRUE
);
1613 /**************************************************************************
1614 * mciGetErrorStringW [WINMM.@]
1616 BOOL WINAPI
mciGetErrorStringW(DWORD wError
, LPWSTR lpstrBuffer
, UINT uLength
)
1618 LPSTR bufstr
= HeapAlloc(GetProcessHeap(), 0, uLength
);
1619 BOOL ret
= mciGetErrorStringA(wError
, bufstr
, uLength
);
1621 MultiByteToWideChar( CP_ACP
, 0, bufstr
, -1, lpstrBuffer
, uLength
);
1622 HeapFree(GetProcessHeap(), 0, bufstr
);
1626 /**************************************************************************
1627 * mciGetErrorString [MMSYSTEM.706]
1629 BOOL16 WINAPI
mciGetErrorString16(DWORD wError
, LPSTR lpstrBuffer
, UINT16 uLength
)
1631 return mciGetErrorStringA(wError
, lpstrBuffer
, uLength
);
1634 /**************************************************************************
1635 * mciGetErrorStringA [WINMM.@]
1637 BOOL WINAPI
mciGetErrorStringA(DWORD dwError
, LPSTR lpstrBuffer
, UINT uLength
)
1641 if (lpstrBuffer
!= NULL
&& uLength
> 0 &&
1642 dwError
>= MCIERR_BASE
&& dwError
<= MCIERR_CUSTOM_DRIVER_BASE
) {
1644 if (LoadStringA(MULTIMEDIA_GetIData()->hWinMM32Instance
,
1645 dwError
, lpstrBuffer
, uLength
) > 0) {
1652 /**************************************************************************
1653 * mciDriverNotify [MMSYSTEM.711]
1655 BOOL16 WINAPI
mciDriverNotify16(HWND16 hWndCallBack
, UINT16 wDevID
, UINT16 wStatus
)
1657 TRACE("(%04X, %04x, %04X)\n", hWndCallBack
, wDevID
, wStatus
);
1659 return PostMessageA(hWndCallBack
, MM_MCINOTIFY
, wStatus
, wDevID
);
1662 /**************************************************************************
1663 * mciDriverNotify [WINMM.@]
1665 BOOL WINAPI
mciDriverNotify(HWND hWndCallBack
, UINT wDevID
, UINT wStatus
)
1668 TRACE("(%08X, %04x, %04X)\n", hWndCallBack
, wDevID
, wStatus
);
1670 return PostMessageA(hWndCallBack
, MM_MCINOTIFY
, wStatus
, wDevID
);
1673 /**************************************************************************
1674 * mciGetDriverData [MMSYSTEM.708]
1676 DWORD WINAPI
mciGetDriverData16(UINT16 uDeviceID
)
1678 return mciGetDriverData(uDeviceID
);
1681 /**************************************************************************
1682 * mciGetDriverData [WINMM.@]
1684 DWORD WINAPI
mciGetDriverData(UINT uDeviceID
)
1686 LPWINE_MCIDRIVER wmd
;
1688 TRACE("(%04x)\n", uDeviceID
);
1690 wmd
= MCI_GetDriver(uDeviceID
);
1693 WARN("Bad uDeviceID\n");
1697 return wmd
->dwPrivate
;
1700 /**************************************************************************
1701 * mciSetDriverData [MMSYSTEM.707]
1703 BOOL16 WINAPI
mciSetDriverData16(UINT16 uDeviceID
, DWORD data
)
1705 return mciSetDriverData(uDeviceID
, data
);
1708 /**************************************************************************
1709 * mciSetDriverData [WINMM.@]
1711 BOOL WINAPI
mciSetDriverData(UINT uDeviceID
, DWORD data
)
1713 LPWINE_MCIDRIVER wmd
;
1715 TRACE("(%04x, %08lx)\n", uDeviceID
, data
);
1717 wmd
= MCI_GetDriver(uDeviceID
);
1720 WARN("Bad uDeviceID\n");
1724 wmd
->dwPrivate
= data
;
1728 /**************************************************************************
1729 * mciSendCommandA [WINMM.@]
1731 DWORD WINAPI
mciSendCommandA(UINT wDevID
, UINT wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1735 TRACE("(%08x, %s, %08lx, %08lx)\n",
1736 wDevID
, MCI_MessageToString(wMsg
), dwParam1
, dwParam2
);
1738 dwRet
= MCI_SendCommand(wDevID
, wMsg
, dwParam1
, dwParam2
, TRUE
);
1739 dwRet
= MCI_CleanUp(dwRet
, wMsg
, dwParam2
, TRUE
);
1740 TRACE("=> %08lx\n", dwRet
);
1744 /**************************************************************************
1745 * mciSendCommandW [WINMM.@]
1747 DWORD WINAPI
mciSendCommandW(UINT wDevID
, UINT wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1749 FIXME("(%08x, %s, %08lx, %08lx): stub\n",
1750 wDevID
, MCI_MessageToString(wMsg
), dwParam1
, dwParam2
);
1751 return MCIERR_UNSUPPORTED_FUNCTION
;
1754 /**************************************************************************
1755 * mciSendCommand [MMSYSTEM.701]
1757 DWORD WINAPI
mciSendCommand16(UINT16 wDevID
, UINT16 wMsg
, DWORD dwParam1
, DWORD dwParam2
)
1761 TRACE("(%04X, %s, %08lX, %08lX)\n",
1762 wDevID
, MCI_MessageToString(wMsg
), dwParam1
, dwParam2
);
1764 dwRet
= MCI_SendCommand(wDevID
, wMsg
, dwParam1
, dwParam2
, FALSE
);
1765 dwRet
= MCI_CleanUp(dwRet
, wMsg
, dwParam2
, FALSE
);
1766 TRACE("=> %ld\n", dwRet
);
1770 /**************************************************************************
1771 * mciGetDeviceID [MMSYSTEM.703]
1773 UINT16 WINAPI
mciGetDeviceID16(LPCSTR lpstrName
)
1775 TRACE("(\"%s\")\n", lpstrName
);
1777 return MCI_GetDriverFromString(lpstrName
);
1780 /**************************************************************************
1781 * mciGetDeviceIDA [WINMM.@]
1783 UINT WINAPI
mciGetDeviceIDA(LPCSTR lpstrName
)
1785 return MCI_GetDriverFromString(lpstrName
);
1788 /**************************************************************************
1789 * mciGetDeviceIDW [WINMM.@]
1791 UINT WINAPI
mciGetDeviceIDW(LPCWSTR lpwstrName
)
1796 lpstrName
= HEAP_strdupWtoA(GetProcessHeap(), 0, lpwstrName
);
1797 ret
= MCI_GetDriverFromString(lpstrName
);
1798 HeapFree(GetProcessHeap(), 0, lpstrName
);
1802 /**************************************************************************
1803 * MCI_DefYieldProc [internal]
1805 UINT WINAPI
MCI_DefYieldProc(MCIDEVICEID wDevID
, DWORD data
)
1809 TRACE("(0x%04x, 0x%08lx)\n", wDevID
, data
);
1811 if ((HIWORD(data
) != 0 && GetActiveWindow() != HIWORD(data
)) ||
1812 (GetAsyncKeyState(LOWORD(data
)) & 1) == 0) {
1818 msg
.hwnd
= HIWORD(data
);
1819 while (!PeekMessageA(&msg
, HIWORD(data
), WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
));
1825 /**************************************************************************
1826 * mciSetYieldProc [MMSYSTEM.714]
1828 BOOL16 WINAPI
mciSetYieldProc16(UINT16 uDeviceID
, YIELDPROC16 fpYieldProc
, DWORD dwYieldData
)
1830 LPWINE_MCIDRIVER wmd
;
1832 TRACE("(%u, %p, %08lx)\n", uDeviceID
, fpYieldProc
, dwYieldData
);
1834 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
1835 WARN("Bad uDeviceID\n");
1839 wmd
->lpfnYieldProc
= (YIELDPROC
)fpYieldProc
;
1840 wmd
->dwYieldData
= dwYieldData
;
1846 /**************************************************************************
1847 * mciSetYieldProc [WINMM.@]
1849 BOOL WINAPI
mciSetYieldProc(UINT uDeviceID
, YIELDPROC fpYieldProc
, DWORD dwYieldData
)
1851 LPWINE_MCIDRIVER wmd
;
1853 TRACE("(%u, %p, %08lx)\n", uDeviceID
, fpYieldProc
, dwYieldData
);
1855 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
1856 WARN("Bad uDeviceID\n");
1860 wmd
->lpfnYieldProc
= fpYieldProc
;
1861 wmd
->dwYieldData
= dwYieldData
;
1867 /**************************************************************************
1868 * mciGetDeviceIDFromElementID [MMSYSTEM.715]
1870 UINT16 WINAPI
mciGetDeviceIDFromElementID16(DWORD dwElementID
, LPCSTR lpstrType
)
1872 FIXME("(%lu, %s) stub\n", dwElementID
, lpstrType
);
1876 /**************************************************************************
1877 * mciGetDeviceIDFromElementIDW [WINMM.@]
1879 UINT WINAPI
mciGetDeviceIDFromElementIDW(DWORD dwElementID
, LPCWSTR lpstrType
)
1881 /* FIXME: that's rather strange, there is no
1882 * mciGetDeviceIDFromElementID32A in winmm.spec
1884 FIXME("(%lu, %p) stub\n", dwElementID
, lpstrType
);
1888 /**************************************************************************
1889 * mciGetYieldProc [MMSYSTEM.716]
1891 YIELDPROC16 WINAPI
mciGetYieldProc16(UINT16 uDeviceID
, DWORD
* lpdwYieldData
)
1893 LPWINE_MCIDRIVER wmd
;
1895 TRACE("(%u, %p)\n", uDeviceID
, lpdwYieldData
);
1897 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
1898 WARN("Bad uDeviceID\n");
1901 if (!wmd
->lpfnYieldProc
) {
1902 WARN("No proc set\n");
1906 WARN("Proc is 32 bit\n");
1909 return (YIELDPROC16
)wmd
->lpfnYieldProc
;
1912 /**************************************************************************
1913 * mciGetYieldProc [WINMM.@]
1915 YIELDPROC WINAPI
mciGetYieldProc(UINT uDeviceID
, DWORD
* lpdwYieldData
)
1917 LPWINE_MCIDRIVER wmd
;
1919 TRACE("(%u, %p)\n", uDeviceID
, lpdwYieldData
);
1921 if (!(wmd
= MCI_GetDriver(uDeviceID
))) {
1922 WARN("Bad uDeviceID\n");
1925 if (!wmd
->lpfnYieldProc
) {
1926 WARN("No proc set\n");
1930 WARN("Proc is 32 bit\n");
1933 return wmd
->lpfnYieldProc
;
1936 /**************************************************************************
1937 * mciGetCreatorTask [MMSYSTEM.717]
1939 HTASK16 WINAPI
mciGetCreatorTask16(UINT16 uDeviceID
)
1941 return mciGetCreatorTask(uDeviceID
);
1944 /**************************************************************************
1945 * mciGetCreatorTask [WINMM.@]
1947 HTASK WINAPI
mciGetCreatorTask(UINT uDeviceID
)
1949 LPWINE_MCIDRIVER wmd
;
1952 TRACE("(%u)\n", uDeviceID
);
1954 ret
= (!(wmd
= MCI_GetDriver(uDeviceID
))) ? 0 : wmd
->hCreatorTask
;
1956 TRACE("=> %04x\n", ret
);
1960 /**************************************************************************
1961 * mciDriverYield [MMSYSTEM.710]
1963 UINT16 WINAPI
mciDriverYield16(UINT16 uDeviceID
)
1965 LPWINE_MCIDRIVER wmd
;
1968 /* TRACE("(%04x)\n", uDeviceID); */
1970 if (!(wmd
= MCI_GetDriver(uDeviceID
)) || !wmd
->lpfnYieldProc
|| wmd
->bIs32
) {
1973 ret
= wmd
->lpfnYieldProc(uDeviceID
, wmd
->dwYieldData
);
1979 /**************************************************************************
1980 * mciDriverYield [WINMM.@]
1982 UINT WINAPI
mciDriverYield(UINT uDeviceID
)
1984 LPWINE_MCIDRIVER wmd
;
1987 TRACE("(%04x)\n", uDeviceID
);
1989 if (!(wmd
= MCI_GetDriver(uDeviceID
)) || !wmd
->lpfnYieldProc
|| !wmd
->bIs32
) {
1992 ret
= wmd
->lpfnYieldProc(uDeviceID
, wmd
->dwYieldData
);
1998 /**************************************************************************
1999 * midiOutGetNumDevs [WINMM.@]
2001 UINT WINAPI
midiOutGetNumDevs(void)
2003 return MMDRV_GetNum(MMDRV_MIDIOUT
);
2006 /**************************************************************************
2007 * midiOutGetNumDevs [MMSYSTEM.201]
2009 UINT16 WINAPI
midiOutGetNumDevs16(void)
2011 return MMDRV_GetNum(MMDRV_MIDIOUT
);
2014 /**************************************************************************
2015 * midiOutGetDevCapsW [WINMM.@]
2017 UINT WINAPI
midiOutGetDevCapsW(UINT uDeviceID
, LPMIDIOUTCAPSW lpCaps
,
2023 ret
= midiOutGetDevCapsA(uDeviceID
, &mocA
, sizeof(mocA
));
2024 lpCaps
->wMid
= mocA
.wMid
;
2025 lpCaps
->wPid
= mocA
.wPid
;
2026 lpCaps
->vDriverVersion
= mocA
.vDriverVersion
;
2027 MultiByteToWideChar( CP_ACP
, 0, mocA
.szPname
, -1, lpCaps
->szPname
,
2028 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
2029 lpCaps
->wTechnology
= mocA
.wTechnology
;
2030 lpCaps
->wVoices
= mocA
.wVoices
;
2031 lpCaps
->wNotes
= mocA
.wNotes
;
2032 lpCaps
->wChannelMask
= mocA
.wChannelMask
;
2033 lpCaps
->dwSupport
= mocA
.dwSupport
;
2037 /**************************************************************************
2038 * midiOutGetDevCapsA [WINMM.@]
2040 UINT WINAPI
midiOutGetDevCapsA(UINT uDeviceID
, LPMIDIOUTCAPSA lpCaps
,
2045 TRACE("(%u, %p, %u);\n", uDeviceID
, lpCaps
, uSize
);
2047 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
2049 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_MIDIOUT
, TRUE
)) == NULL
)
2050 return MMSYSERR_INVALHANDLE
;
2052 return MMDRV_Message(wmld
, MODM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
2055 /**************************************************************************
2056 * midiOutGetDevCaps [MMSYSTEM.202]
2058 UINT16 WINAPI
midiOutGetDevCaps16(UINT16 uDeviceID
, LPMIDIOUTCAPS16 lpCaps
,
2064 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
2066 dwRet
= midiOutGetDevCapsA(uDeviceID
, &capsA
, sizeof(capsA
));
2067 if (dwRet
== MMSYSERR_NOERROR
) {
2068 lpCaps
->wMid
= capsA
.wMid
;
2069 lpCaps
->wPid
= capsA
.wPid
;
2070 lpCaps
->vDriverVersion
= capsA
.vDriverVersion
;
2071 strcpy(lpCaps
->szPname
, capsA
.szPname
);
2072 lpCaps
->wTechnology
= capsA
.wTechnology
;
2073 lpCaps
->wVoices
= capsA
.wVoices
;
2074 lpCaps
->wNotes
= capsA
.wNotes
;
2075 lpCaps
->wChannelMask
= capsA
.wChannelMask
;
2076 lpCaps
->dwSupport
= capsA
.dwSupport
;
2081 /**************************************************************************
2082 * MIDI_GetErrorText [internal]
2084 static UINT16
MIDI_GetErrorText(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
2086 UINT16 ret
= MMSYSERR_BADERRNUM
;
2088 if (lpText
== NULL
) {
2089 ret
= MMSYSERR_INVALPARAM
;
2090 } else if (uSize
== 0) {
2091 ret
= MMSYSERR_NOERROR
;
2093 /* test has been removed 'coz MMSYSERR_BASE is 0, and gcc did emit
2094 * a warning for the test was always true */
2095 (/*uError >= MMSYSERR_BASE && */ uError
<= MMSYSERR_LASTERROR
) ||
2096 (uError
>= MIDIERR_BASE
&& uError
<= MIDIERR_LASTERROR
)) {
2098 if (LoadStringA(MULTIMEDIA_GetIData()->hWinMM32Instance
,
2099 uError
, lpText
, uSize
) > 0) {
2100 ret
= MMSYSERR_NOERROR
;
2106 /**************************************************************************
2107 * midiOutGetErrorTextA [WINMM.@]
2109 UINT WINAPI
midiOutGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
2111 return MIDI_GetErrorText(uError
, lpText
, uSize
);
2114 /**************************************************************************
2115 * midiOutGetErrorTextW [WINMM.@]
2117 UINT WINAPI
midiOutGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
2119 LPSTR xstr
= HeapAlloc(GetProcessHeap(), 0, uSize
);
2122 ret
= MIDI_GetErrorText(uError
, xstr
, uSize
);
2123 MultiByteToWideChar( CP_ACP
, 0, xstr
, -1, lpText
, uSize
);
2124 HeapFree(GetProcessHeap(), 0, xstr
);
2128 /**************************************************************************
2129 * midiOutGetErrorText [MMSYSTEM.203]
2131 UINT16 WINAPI
midiOutGetErrorText16(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
2133 return MIDI_GetErrorText(uError
, lpText
, uSize
);
2136 /**************************************************************************
2137 * MIDI_OutAlloc [internal]
2139 static LPWINE_MIDI
MIDI_OutAlloc(HMIDIOUT
* lphMidiOut
, LPDWORD lpdwCallback
,
2140 LPDWORD lpdwInstance
, LPDWORD lpdwFlags
,
2141 DWORD cIDs
, MIDIOPENSTRMID
* lpIDs
, BOOL bFrom32
)
2147 size
= sizeof(WINE_MIDI
) + (cIDs
? (cIDs
-1) : 0) * sizeof(MIDIOPENSTRMID
);
2149 lpwm
= (LPWINE_MIDI
)MMDRV_Alloc(size
, MMDRV_MIDIOUT
, &hMidiOut
, lpdwFlags
,
2150 lpdwCallback
, lpdwInstance
, bFrom32
);
2152 if (lphMidiOut
!= NULL
)
2153 *lphMidiOut
= hMidiOut
;
2156 lpwm
->mod
.hMidi
= hMidiOut
;
2157 lpwm
->mod
.dwCallback
= *lpdwCallback
;
2158 lpwm
->mod
.dwInstance
= *lpdwInstance
;
2159 lpwm
->mod
.dnDevNode
= 0;
2160 lpwm
->mod
.cIds
= cIDs
;
2162 memcpy(&(lpwm
->mod
.rgIds
), lpIDs
, cIDs
* sizeof(MIDIOPENSTRMID
));
2167 UINT
MMSYSTEM_midiOutOpen(HMIDIOUT
* lphMidiOut
, UINT uDeviceID
, DWORD dwCallback
,
2168 DWORD dwInstance
, DWORD dwFlags
, BOOL bFrom32
)
2174 TRACE("(%p, %d, %08lX, %08lX, %08lX);\n",
2175 lphMidiOut
, uDeviceID
, dwCallback
, dwInstance
, dwFlags
);
2177 if (lphMidiOut
!= NULL
) *lphMidiOut
= 0;
2179 lpwm
= MIDI_OutAlloc(&hMidiOut
, &dwCallback
, &dwInstance
, &dwFlags
,
2183 return MMSYSERR_NOMEM
;
2185 lpwm
->mld
.uDeviceID
= uDeviceID
;
2187 dwRet
= MMDRV_Open((LPWINE_MLD
)lpwm
, MODM_OPEN
, (DWORD
)&lpwm
->mod
,
2190 if (dwRet
!= MMSYSERR_NOERROR
) {
2191 MMDRV_Free(hMidiOut
, (LPWINE_MLD
)lpwm
);
2195 if (lphMidiOut
) *lphMidiOut
= hMidiOut
;
2196 TRACE("=> %d hMidi=%04x\n", dwRet
, hMidiOut
);
2201 /**************************************************************************
2202 * midiOutOpen [WINMM.@]
2204 UINT WINAPI
midiOutOpen(HMIDIOUT
* lphMidiOut
, UINT uDeviceID
,
2205 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
2207 return MMSYSTEM_midiOutOpen(lphMidiOut
, uDeviceID
, dwCallback
,
2208 dwInstance
, dwFlags
, TRUE
);
2211 /**************************************************************************
2212 * midiOutOpen [MMSYSTEM.204]
2214 UINT16 WINAPI
midiOutOpen16(HMIDIOUT16
* lphMidiOut
, UINT16 uDeviceID
,
2215 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
2220 ret
= MMSYSTEM_midiOutOpen(&hmo
, uDeviceID
, dwCallback
, dwInstance
,
2223 if (lphMidiOut
!= NULL
) *lphMidiOut
= hmo
;
2227 /**************************************************************************
2228 * midiOutClose [WINMM.@]
2230 UINT WINAPI
midiOutClose(HMIDIOUT hMidiOut
)
2235 TRACE("(%04X)\n", hMidiOut
);
2237 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2238 return MMSYSERR_INVALHANDLE
;
2240 dwRet
= MMDRV_Close(wmld
, MODM_CLOSE
);
2241 MMDRV_Free(hMidiOut
, wmld
);
2246 /**************************************************************************
2247 * midiOutClose [MMSYSTEM.205]
2249 UINT16 WINAPI
midiOutClose16(HMIDIOUT16 hMidiOut
)
2251 return midiOutClose(hMidiOut
);
2254 /**************************************************************************
2255 * midiOutPrepareHeader [WINMM.@]
2257 UINT WINAPI
midiOutPrepareHeader(HMIDIOUT hMidiOut
,
2258 MIDIHDR
* lpMidiOutHdr
, UINT uSize
)
2262 TRACE("(%04X, %p, %d)\n", hMidiOut
, lpMidiOutHdr
, uSize
);
2264 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2265 return MMSYSERR_INVALHANDLE
;
2267 return MMDRV_Message(wmld
, MODM_PREPARE
, (DWORD
)lpMidiOutHdr
, uSize
, TRUE
);
2270 /**************************************************************************
2271 * midiOutPrepareHeader [MMSYSTEM.206]
2273 UINT16 WINAPI
midiOutPrepareHeader16(HMIDIOUT16 hMidiOut
, /* [in] */
2274 SEGPTR lpsegMidiOutHdr
, /* [???] */
2275 UINT16 uSize
) /* [in] */
2279 TRACE("(%04X, %08lx, %d)\n", hMidiOut
, lpsegMidiOutHdr
, uSize
);
2281 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2282 return MMSYSERR_INVALHANDLE
;
2284 return MMDRV_Message(wmld
, MODM_PREPARE
, lpsegMidiOutHdr
, uSize
, FALSE
);
2287 /**************************************************************************
2288 * midiOutUnprepareHeader [WINMM.@]
2290 UINT WINAPI
midiOutUnprepareHeader(HMIDIOUT hMidiOut
,
2291 MIDIHDR
* lpMidiOutHdr
, UINT uSize
)
2295 TRACE("(%04X, %p, %d)\n", hMidiOut
, lpMidiOutHdr
, uSize
);
2297 if (!(lpMidiOutHdr
->dwFlags
& MHDR_PREPARED
)) {
2298 return MMSYSERR_NOERROR
;
2301 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2302 return MMSYSERR_INVALHANDLE
;
2304 return MMDRV_Message(wmld
, MODM_UNPREPARE
, (DWORD
)lpMidiOutHdr
, uSize
, TRUE
);
2307 /**************************************************************************
2308 * midiOutUnprepareHeader [MMSYSTEM.207]
2310 UINT16 WINAPI
midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut
, /* [in] */
2311 SEGPTR lpsegMidiOutHdr
, /* [???] */
2312 UINT16 uSize
) /* [in] */
2315 LPMIDIHDR16 lpMidiOutHdr
= MapSL(lpsegMidiOutHdr
);
2317 TRACE("(%04X, %08lx, %d)\n", hMidiOut
, lpsegMidiOutHdr
, uSize
);
2319 if (!(lpMidiOutHdr
->dwFlags
& MHDR_PREPARED
)) {
2320 return MMSYSERR_NOERROR
;
2323 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2324 return MMSYSERR_INVALHANDLE
;
2326 return MMDRV_Message(wmld
, MODM_UNPREPARE
, (DWORD
)lpsegMidiOutHdr
, uSize
, FALSE
);
2329 /**************************************************************************
2330 * midiOutShortMsg [WINMM.@]
2332 UINT WINAPI
midiOutShortMsg(HMIDIOUT hMidiOut
, DWORD dwMsg
)
2336 TRACE("(%04X, %08lX)\n", hMidiOut
, dwMsg
);
2338 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2339 return MMSYSERR_INVALHANDLE
;
2341 return MMDRV_Message(wmld
, MODM_DATA
, dwMsg
, 0L, FALSE
);
2344 /**************************************************************************
2345 * midiOutShortMsg [MMSYSTEM.208]
2347 UINT16 WINAPI
midiOutShortMsg16(HMIDIOUT16 hMidiOut
, DWORD dwMsg
)
2349 return midiOutShortMsg(hMidiOut
, dwMsg
);
2352 /**************************************************************************
2353 * midiOutLongMsg [WINMM.@]
2355 UINT WINAPI
midiOutLongMsg(HMIDIOUT hMidiOut
,
2356 MIDIHDR
* lpMidiOutHdr
, UINT uSize
)
2360 TRACE("(%04X, %p, %d)\n", hMidiOut
, lpMidiOutHdr
, uSize
);
2362 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2363 return MMSYSERR_INVALHANDLE
;
2365 return MMDRV_Message(wmld
, MODM_LONGDATA
, (DWORD
)lpMidiOutHdr
, uSize
, TRUE
);
2368 /**************************************************************************
2369 * midiOutLongMsg [MMSYSTEM.209]
2371 UINT16 WINAPI
midiOutLongMsg16(HMIDIOUT16 hMidiOut
, /* [in] */
2372 LPMIDIHDR16 lpsegMidiOutHdr
, /* [???] NOTE: SEGPTR */
2373 UINT16 uSize
) /* [in] */
2377 TRACE("(%04X, %p, %d)\n", hMidiOut
, lpsegMidiOutHdr
, uSize
);
2379 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2380 return MMSYSERR_INVALHANDLE
;
2382 return MMDRV_Message(wmld
, MODM_LONGDATA
, (DWORD
)lpsegMidiOutHdr
, uSize
, FALSE
);
2385 /**************************************************************************
2386 * midiOutReset [WINMM.@]
2388 UINT WINAPI
midiOutReset(HMIDIOUT hMidiOut
)
2392 TRACE("(%04X)\n", hMidiOut
);
2394 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2395 return MMSYSERR_INVALHANDLE
;
2397 return MMDRV_Message(wmld
, MODM_RESET
, 0L, 0L, TRUE
);
2400 /**************************************************************************
2401 * midiOutReset [MMSYSTEM.210]
2403 UINT16 WINAPI
midiOutReset16(HMIDIOUT16 hMidiOut
)
2405 return midiOutReset(hMidiOut
);
2408 /**************************************************************************
2409 * midiOutGetVolume [WINMM.@]
2411 UINT WINAPI
midiOutGetVolume(UINT uDeviceID
, DWORD
* lpdwVolume
)
2415 TRACE("(%04X, %p);\n", uDeviceID
, lpdwVolume
);
2417 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_MIDIOUT
, TRUE
)) == NULL
)
2418 return MMSYSERR_INVALHANDLE
;
2420 return MMDRV_Message(wmld
, MODM_GETVOLUME
, (DWORD
)lpdwVolume
, 0L, TRUE
);
2423 /**************************************************************************
2424 * midiOutGetVolume [MMSYSTEM.211]
2426 UINT16 WINAPI
midiOutGetVolume16(UINT16 uDeviceID
, DWORD
* lpdwVolume
)
2428 return midiOutGetVolume(uDeviceID
, lpdwVolume
);
2431 /**************************************************************************
2432 * midiOutSetVolume [WINMM.@]
2434 UINT WINAPI
midiOutSetVolume(UINT uDeviceID
, DWORD dwVolume
)
2438 TRACE("(%04X, %ld);\n", uDeviceID
, dwVolume
);
2440 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_MIDIOUT
, TRUE
)) == NULL
)
2441 return MMSYSERR_INVALHANDLE
;
2443 return MMDRV_Message(wmld
, MODM_SETVOLUME
, dwVolume
, 0L, TRUE
);
2446 /**************************************************************************
2447 * midiOutSetVolume [MMSYSTEM.212]
2449 UINT16 WINAPI
midiOutSetVolume16(UINT16 uDeviceID
, DWORD dwVolume
)
2451 return midiOutSetVolume(uDeviceID
, dwVolume
);
2454 /**************************************************************************
2455 * midiOutCachePatches [WINMM.@]
2457 UINT WINAPI
midiOutCachePatches(HMIDIOUT hMidiOut
, UINT uBank
,
2458 WORD
* lpwPatchArray
, UINT uFlags
)
2460 /* not really necessary to support this */
2461 FIXME("not supported yet\n");
2462 return MMSYSERR_NOTSUPPORTED
;
2465 /**************************************************************************
2466 * midiOutCachePatches [MMSYSTEM.213]
2468 UINT16 WINAPI
midiOutCachePatches16(HMIDIOUT16 hMidiOut
, UINT16 uBank
,
2469 WORD
* lpwPatchArray
, UINT16 uFlags
)
2471 return midiOutCachePatches(hMidiOut
, uBank
, lpwPatchArray
, uFlags
);
2474 /**************************************************************************
2475 * midiOutCacheDrumPatches [WINMM.@]
2477 UINT WINAPI
midiOutCacheDrumPatches(HMIDIOUT hMidiOut
, UINT uPatch
,
2478 WORD
* lpwKeyArray
, UINT uFlags
)
2480 FIXME("not supported yet\n");
2481 return MMSYSERR_NOTSUPPORTED
;
2484 /**************************************************************************
2485 * midiOutCacheDrumPatches [MMSYSTEM.214]
2487 UINT16 WINAPI
midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut
, UINT16 uPatch
,
2488 WORD
* lpwKeyArray
, UINT16 uFlags
)
2490 return midiOutCacheDrumPatches16(hMidiOut
, uPatch
, lpwKeyArray
, uFlags
);
2493 /**************************************************************************
2494 * midiOutGetID [WINMM.@]
2496 UINT WINAPI
midiOutGetID(HMIDIOUT hMidiOut
, UINT
* lpuDeviceID
)
2500 TRACE("(%04X, %p)\n", hMidiOut
, lpuDeviceID
);
2502 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
2503 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2504 return MMSYSERR_INVALHANDLE
;
2506 *lpuDeviceID
= wmld
->uDeviceID
;
2507 return MMSYSERR_NOERROR
;
2510 /**************************************************************************
2511 * midiOutGetID [MMSYSTEM.215]
2513 UINT16 WINAPI
midiOutGetID16(HMIDIOUT16 hMidiOut
, UINT16
* lpuDeviceID
)
2517 TRACE("(%04X, %p)\n", hMidiOut
, lpuDeviceID
);
2519 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
2520 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2521 return MMSYSERR_INVALHANDLE
;
2523 *lpuDeviceID
= wmld
->uDeviceID
;
2524 return MMSYSERR_NOERROR
;
2527 /**************************************************************************
2528 * midiOutMessage [WINMM.@]
2530 DWORD WINAPI
midiOutMessage(HMIDIOUT hMidiOut
, UINT uMessage
,
2531 DWORD dwParam1
, DWORD dwParam2
)
2535 TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiOut
, uMessage
, dwParam1
, dwParam2
);
2537 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
) {
2539 if (uMessage
== 0x0001) {
2540 *(LPDWORD
)dwParam1
= 1;
2543 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, TRUE
)) != NULL
) {
2544 return MMDRV_PhysicalFeatures(wmld
, uMessage
, dwParam1
, dwParam2
);
2546 return MMSYSERR_INVALHANDLE
;
2552 FIXME("can't handle OPEN or CLOSE message!\n");
2553 return MMSYSERR_NOTSUPPORTED
;
2555 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
2558 /**************************************************************************
2559 * midiOutMessage [MMSYSTEM.216]
2561 DWORD WINAPI
midiOutMessage16(HMIDIOUT16 hMidiOut
, UINT16 uMessage
,
2562 DWORD dwParam1
, DWORD dwParam2
)
2566 TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiOut
, uMessage
, dwParam1
, dwParam2
);
2568 if ((wmld
= MMDRV_Get(hMidiOut
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
2569 return MMSYSERR_INVALHANDLE
;
2574 FIXME("can't handle OPEN or CLOSE message!\n");
2575 return MMSYSERR_NOTSUPPORTED
;
2577 case MODM_GETVOLUME
:
2578 return midiOutGetVolume16(hMidiOut
, MapSL(dwParam1
));
2580 return midiOutLongMsg16(hMidiOut
, MapSL(dwParam1
), dwParam2
);
2582 /* lpMidiOutHdr is still a segmented pointer for this function */
2583 return midiOutPrepareHeader16(hMidiOut
, dwParam1
, dwParam2
);
2584 case MODM_UNPREPARE
:
2585 return midiOutUnprepareHeader16(hMidiOut
, dwParam1
, dwParam2
);
2587 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
2590 /**************************************************************************
2591 * midiInGetNumDevs [WINMM.@]
2593 UINT WINAPI
midiInGetNumDevs(void)
2595 return MMDRV_GetNum(MMDRV_MIDIIN
);
2598 /**************************************************************************
2599 * midiInGetNumDevs [MMSYSTEM.301]
2601 UINT16 WINAPI
midiInGetNumDevs16(void)
2603 return MMDRV_GetNum(MMDRV_MIDIIN
);
2606 /**************************************************************************
2607 * midiInGetDevCapsW [WINMM.@]
2609 UINT WINAPI
midiInGetDevCapsW(UINT uDeviceID
, LPMIDIINCAPSW lpCaps
, UINT uSize
)
2612 UINT ret
= midiInGetDevCapsA(uDeviceID
, &micA
, uSize
);
2614 if (ret
== MMSYSERR_NOERROR
) {
2615 lpCaps
->wMid
= micA
.wMid
;
2616 lpCaps
->wPid
= micA
.wPid
;
2617 lpCaps
->vDriverVersion
= micA
.vDriverVersion
;
2618 MultiByteToWideChar( CP_ACP
, 0, micA
.szPname
, -1, lpCaps
->szPname
,
2619 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
2620 lpCaps
->dwSupport
= micA
.dwSupport
;
2625 /**************************************************************************
2626 * midiInGetDevCapsA [WINMM.@]
2628 UINT WINAPI
midiInGetDevCapsA(UINT uDeviceID
, LPMIDIINCAPSA lpCaps
, UINT uSize
)
2632 TRACE("(%d, %p, %d);\n", uDeviceID
, lpCaps
, uSize
);
2634 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_MIDIIN
, TRUE
)) == NULL
)
2635 return MMSYSERR_INVALHANDLE
;
2637 return MMDRV_Message(wmld
, MIDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
2640 /**************************************************************************
2641 * midiInGetDevCaps [MMSYSTEM.302]
2643 UINT16 WINAPI
midiInGetDevCaps16(UINT16 uDeviceID
, LPMIDIINCAPS16 lpCaps
,
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 strcpy(lpCaps
->szPname
, micA
.szPname
);
2654 lpCaps
->dwSupport
= micA
.dwSupport
;
2660 /**************************************************************************
2661 * midiInGetErrorTextW [WINMM.@]
2663 UINT WINAPI
midiInGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
2665 LPSTR xstr
= HeapAlloc(GetProcessHeap(), 0, uSize
);
2666 UINT ret
= MIDI_GetErrorText(uError
, xstr
, uSize
);
2668 MultiByteToWideChar( CP_ACP
, 0, xstr
, -1, lpText
, uSize
);
2669 HeapFree(GetProcessHeap(), 0, xstr
);
2673 /**************************************************************************
2674 * midiInGetErrorTextA [WINMM.@]
2676 UINT WINAPI
midiInGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
2678 return MIDI_GetErrorText(uError
, lpText
, uSize
);
2681 /**************************************************************************
2682 * midiInGetErrorText [MMSYSTEM.303]
2684 UINT16 WINAPI
midiInGetErrorText16(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
2686 return MIDI_GetErrorText(uError
, lpText
, uSize
);
2689 static UINT
MMSYSTEM_midiInOpen(HMIDIIN
* lphMidiIn
, UINT uDeviceID
, DWORD dwCallback
,
2690 DWORD dwInstance
, DWORD dwFlags
, BOOL bFrom32
)
2696 TRACE("(%p, %d, %08lX, %08lX, %08lX);\n",
2697 lphMidiIn
, uDeviceID
, dwCallback
, dwInstance
, dwFlags
);
2699 if (lphMidiIn
!= NULL
) *lphMidiIn
= 0;
2701 lpwm
= (LPWINE_MIDI
)MMDRV_Alloc(sizeof(WINE_MIDI
), MMDRV_MIDIIN
, &hMidiIn
,
2702 &dwFlags
, &dwCallback
, &dwInstance
, bFrom32
);
2705 return MMSYSERR_NOMEM
;
2707 lpwm
->mod
.hMidi
= hMidiIn
;
2708 lpwm
->mod
.dwCallback
= dwCallback
;
2709 lpwm
->mod
.dwInstance
= dwInstance
;
2711 lpwm
->mld
.uDeviceID
= uDeviceID
;
2712 dwRet
= MMDRV_Open(&lpwm
->mld
, MIDM_OPEN
, (DWORD
)&lpwm
->mod
, dwFlags
);
2714 if (dwRet
!= MMSYSERR_NOERROR
) {
2715 MMDRV_Free(hMidiIn
, &lpwm
->mld
);
2718 if (lphMidiIn
!= NULL
) *lphMidiIn
= hMidiIn
;
2719 TRACE("=> %ld hMidi=%04x\n", dwRet
, hMidiIn
);
2724 /**************************************************************************
2725 * midiInOpen [WINMM.@]
2727 UINT WINAPI
midiInOpen(HMIDIIN
* lphMidiIn
, UINT uDeviceID
,
2728 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
2730 return MMSYSTEM_midiInOpen(lphMidiIn
, uDeviceID
, dwCallback
,
2731 dwInstance
, dwFlags
, TRUE
);
2734 /**************************************************************************
2735 * midiInOpen [MMSYSTEM.304]
2737 UINT16 WINAPI
midiInOpen16(HMIDIIN16
* lphMidiIn
, UINT16 uDeviceID
,
2738 DWORD dwCallback
, DWORD dwInstance
, DWORD dwFlags
)
2743 ret
= MMSYSTEM_midiInOpen(&xhmid
, uDeviceID
, dwCallback
, dwInstance
,
2746 if (lphMidiIn
) *lphMidiIn
= xhmid
;
2750 /**************************************************************************
2751 * midiInClose [WINMM.@]
2753 UINT WINAPI
midiInClose(HMIDIIN hMidiIn
)
2758 TRACE("(%04X)\n", hMidiIn
);
2760 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2761 return MMSYSERR_INVALHANDLE
;
2763 dwRet
= MMDRV_Close(wmld
, MIDM_CLOSE
);
2764 MMDRV_Free(hMidiIn
, wmld
);
2768 /**************************************************************************
2769 * midiInClose [MMSYSTEM.305]
2771 UINT16 WINAPI
midiInClose16(HMIDIIN16 hMidiIn
)
2773 return midiInClose(hMidiIn
);
2776 /**************************************************************************
2777 * midiInPrepareHeader [WINMM.@]
2779 UINT WINAPI
midiInPrepareHeader(HMIDIIN hMidiIn
,
2780 MIDIHDR
* lpMidiInHdr
, UINT uSize
)
2784 TRACE("(%04X, %p, %d)\n", hMidiIn
, lpMidiInHdr
, uSize
);
2786 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2787 return MMSYSERR_INVALHANDLE
;
2789 return MMDRV_Message(wmld
, MIDM_PREPARE
, (DWORD
)lpMidiInHdr
, uSize
, TRUE
);
2792 /**************************************************************************
2793 * midiInPrepareHeader [MMSYSTEM.306]
2795 UINT16 WINAPI
midiInPrepareHeader16(HMIDIIN16 hMidiIn
, /* [in] */
2796 SEGPTR lpsegMidiInHdr
, /* [???] */
2797 UINT16 uSize
) /* [in] */
2801 TRACE("(%04X, %08lx, %d)\n", hMidiIn
, lpsegMidiInHdr
, uSize
);
2803 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2804 return MMSYSERR_INVALHANDLE
;
2806 return MMDRV_Message(wmld
, MIDM_PREPARE
, (DWORD
)lpsegMidiInHdr
, uSize
, FALSE
);
2809 /**************************************************************************
2810 * midiInUnprepareHeader [WINMM.@]
2812 UINT WINAPI
midiInUnprepareHeader(HMIDIIN hMidiIn
,
2813 MIDIHDR
* lpMidiInHdr
, UINT uSize
)
2817 TRACE("(%04X, %p, %d)\n", hMidiIn
, lpMidiInHdr
, uSize
);
2819 if (!(lpMidiInHdr
->dwFlags
& MHDR_PREPARED
)) {
2820 return MMSYSERR_NOERROR
;
2823 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2824 return MMSYSERR_INVALHANDLE
;
2826 return MMDRV_Message(wmld
, MIDM_UNPREPARE
, (DWORD
)lpMidiInHdr
, uSize
, TRUE
);
2829 /**************************************************************************
2830 * midiInUnprepareHeader [MMSYSTEM.307]
2832 UINT16 WINAPI
midiInUnprepareHeader16(HMIDIIN16 hMidiIn
, /* [in] */
2833 SEGPTR lpsegMidiInHdr
, /* [???] */
2834 UINT16 uSize
) /* [in] */
2837 LPMIDIHDR16 lpMidiInHdr
= MapSL(lpsegMidiInHdr
);
2839 TRACE("(%04X, %08lx, %d)\n", hMidiIn
, lpsegMidiInHdr
, uSize
);
2841 if (!(lpMidiInHdr
->dwFlags
& MHDR_PREPARED
)) {
2842 return MMSYSERR_NOERROR
;
2845 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2846 return MMSYSERR_INVALHANDLE
;
2848 return MMDRV_Message(wmld
, MIDM_UNPREPARE
, (DWORD
)lpsegMidiInHdr
, uSize
, FALSE
);
2851 /**************************************************************************
2852 * midiInAddBuffer [WINMM.@]
2854 UINT WINAPI
midiInAddBuffer(HMIDIIN hMidiIn
,
2855 MIDIHDR
* lpMidiInHdr
, UINT uSize
)
2859 TRACE("(%04X, %p, %d)\n", hMidiIn
, lpMidiInHdr
, uSize
);
2861 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2862 return MMSYSERR_INVALHANDLE
;
2864 return MMDRV_Message(wmld
, MIDM_ADDBUFFER
, (DWORD
)lpMidiInHdr
, uSize
, TRUE
);
2867 /**************************************************************************
2868 * midiInAddBuffer [MMSYSTEM.308]
2870 UINT16 WINAPI
midiInAddBuffer16(HMIDIIN16 hMidiIn
, /* [in] */
2871 MIDIHDR16
* lpsegMidiInHdr
, /* [???] NOTE: SEGPTR */
2872 UINT16 uSize
) /* [in] */
2876 TRACE("(%04X, %p, %d)\n", hMidiIn
, lpsegMidiInHdr
, uSize
);
2878 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2879 return MMSYSERR_INVALHANDLE
;
2881 return MMDRV_Message(wmld
, MIDM_ADDBUFFER
, (DWORD
)lpsegMidiInHdr
, uSize
, FALSE
);
2884 /**************************************************************************
2885 * midiInStart [WINMM.@]
2887 UINT WINAPI
midiInStart(HMIDIIN hMidiIn
)
2891 TRACE("(%04X)\n", hMidiIn
);
2893 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2894 return MMSYSERR_INVALHANDLE
;
2896 return MMDRV_Message(wmld
, MIDM_START
, 0L, 0L, TRUE
);
2899 /**************************************************************************
2900 * midiInStart [MMSYSTEM.309]
2902 UINT16 WINAPI
midiInStart16(HMIDIIN16 hMidiIn
)
2904 return midiInStart(hMidiIn
);
2907 /**************************************************************************
2908 * midiInStop [WINMM.@]
2910 UINT WINAPI
midiInStop(HMIDIIN hMidiIn
)
2914 TRACE("(%04X)\n", hMidiIn
);
2916 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2917 return MMSYSERR_INVALHANDLE
;
2919 return MMDRV_Message(wmld
, MIDM_STOP
, 0L, 0L, TRUE
);
2922 /**************************************************************************
2923 * midiInStop [MMSYSTEM.310]
2925 UINT16 WINAPI
midiInStop16(HMIDIIN16 hMidiIn
)
2927 return midiInStop(hMidiIn
);
2930 /**************************************************************************
2931 * midiInReset [WINMM.@]
2933 UINT WINAPI
midiInReset(HMIDIIN hMidiIn
)
2937 TRACE("(%04X)\n", hMidiIn
);
2939 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
2940 return MMSYSERR_INVALHANDLE
;
2942 return MMDRV_Message(wmld
, MIDM_RESET
, 0L, 0L, TRUE
);
2945 /**************************************************************************
2946 * midiInReset [MMSYSTEM.311]
2948 UINT16 WINAPI
midiInReset16(HMIDIIN16 hMidiIn
)
2950 return midiInReset(hMidiIn
);
2953 /**************************************************************************
2954 * midiInGetID [WINMM.@]
2956 UINT WINAPI
midiInGetID(HMIDIIN hMidiIn
, UINT
* lpuDeviceID
)
2960 TRACE("(%04X, %p)\n", hMidiIn
, lpuDeviceID
);
2962 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
2964 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, TRUE
)) == NULL
)
2965 return MMSYSERR_INVALHANDLE
;
2967 *lpuDeviceID
= wmld
->uDeviceID
;
2969 return MMSYSERR_NOERROR
;
2972 /**************************************************************************
2973 * midiInGetID [MMSYSTEM.312]
2975 UINT16 WINAPI
midiInGetID16(HMIDIIN16 hMidiIn
, UINT16
* lpuDeviceID
)
2979 TRACE("(%04X, %p)\n", hMidiIn
, lpuDeviceID
);
2981 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALPARAM
;
2983 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, TRUE
)) == NULL
)
2984 return MMSYSERR_INVALHANDLE
;
2986 *lpuDeviceID
= wmld
->uDeviceID
;
2988 return MMSYSERR_NOERROR
;
2991 /**************************************************************************
2992 * midiInMessage [WINMM.@]
2994 DWORD WINAPI
midiInMessage(HMIDIIN hMidiIn
, UINT uMessage
,
2995 DWORD dwParam1
, DWORD dwParam2
)
2999 TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiIn
, uMessage
, dwParam1
, dwParam2
);
3001 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
3002 return MMSYSERR_INVALHANDLE
;
3007 FIXME("can't handle OPEN or CLOSE message!\n");
3008 return MMSYSERR_NOTSUPPORTED
;
3010 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
3013 /**************************************************************************
3014 * midiInMessage [MMSYSTEM.313]
3016 DWORD WINAPI
midiInMessage16(HMIDIIN16 hMidiIn
, UINT16 uMessage
,
3017 DWORD dwParam1
, DWORD dwParam2
)
3021 TRACE("(%04X, %04X, %08lX, %08lX)\n", hMidiIn
, uMessage
, dwParam1
, dwParam2
);
3026 FIXME("can't handle OPEN or CLOSE message!\n");
3027 return MMSYSERR_NOTSUPPORTED
;
3029 case MIDM_GETDEVCAPS
:
3030 return midiInGetDevCaps16(hMidiIn
, MapSL(dwParam1
), dwParam2
);
3032 return midiInPrepareHeader16(hMidiIn
, dwParam1
, dwParam2
);
3033 case MIDM_UNPREPARE
:
3034 return midiInUnprepareHeader16(hMidiIn
, dwParam1
, dwParam2
);
3035 case MIDM_ADDBUFFER
:
3036 return midiInAddBuffer16(hMidiIn
, MapSL(dwParam1
), dwParam2
);
3039 if ((wmld
= MMDRV_Get(hMidiIn
, MMDRV_MIDIIN
, FALSE
)) == NULL
)
3040 return MMSYSERR_INVALHANDLE
;
3042 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, FALSE
);
3045 typedef struct WINE_MIDIStream
{
3056 LPMIDIHDR lpMidiHdr
;
3059 #define WINE_MSM_HEADER (WM_USER+0)
3060 #define WINE_MSM_STOP (WM_USER+1)
3062 /**************************************************************************
3063 * MMSYSTEM_GetMidiStream [internal]
3065 static BOOL
MMSYSTEM_GetMidiStream(HMIDISTRM hMidiStrm
, WINE_MIDIStream
** lpMidiStrm
, WINE_MIDI
** lplpwm
)
3067 WINE_MIDI
* lpwm
= (LPWINE_MIDI
)MMDRV_Get(hMidiStrm
, MMDRV_MIDIOUT
, FALSE
);
3076 *lpMidiStrm
= (WINE_MIDIStream
*)lpwm
->mod
.rgIds
.dwStreamID
;
3078 return *lpMidiStrm
!= NULL
;
3081 /**************************************************************************
3082 * MMSYSTEM_MidiStream_Convert [internal]
3084 static DWORD
MMSYSTEM_MidiStream_Convert(WINE_MIDIStream
* lpMidiStrm
, DWORD pulse
)
3088 if (lpMidiStrm
->dwTimeDiv
== 0) {
3089 FIXME("Shouldn't happen. lpMidiStrm->dwTimeDiv = 0\n");
3090 } else if (lpMidiStrm
->dwTimeDiv
> 0x8000) { /* SMPTE, unchecked FIXME? */
3091 int nf
= -(char)HIBYTE(lpMidiStrm
->dwTimeDiv
); /* number of frames */
3092 int nsf
= LOBYTE(lpMidiStrm
->dwTimeDiv
); /* number of sub-frames */
3093 ret
= (pulse
* 1000) / (nf
* nsf
);
3095 ret
= (DWORD
)((double)pulse
* ((double)lpMidiStrm
->dwTempo
/ 1000) /
3096 (double)lpMidiStrm
->dwTimeDiv
);
3102 /**************************************************************************
3103 * MMSYSTEM_MidiStream_MessageHandler [internal]
3105 static BOOL
MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream
* lpMidiStrm
, LPWINE_MIDI lpwm
, LPMSG msg
)
3107 LPMIDIHDR lpMidiHdr
;
3111 switch (msg
->message
) {
3113 SetEvent(lpMidiStrm
->hEvent
);
3117 /* this is not quite what MS doc says... */
3118 midiOutReset(lpMidiStrm
->hDevice
);
3119 /* empty list of already submitted buffers */
3120 for (lpMidiHdr
= lpMidiStrm
->lpMidiHdr
; lpMidiHdr
; lpMidiHdr
= (LPMIDIHDR
)lpMidiHdr
->lpNext
) {
3121 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
3122 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
3124 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
, lpMidiStrm
->hDevice
,
3125 MM_MOM_DONE
, lpwm
->mod
.dwInstance
, (DWORD
)lpMidiHdr
, 0L);
3127 lpMidiStrm
->lpMidiHdr
= 0;
3128 SetEvent(lpMidiStrm
->hEvent
);
3130 case WINE_MSM_HEADER
:
3131 /* sets initial tick count for first MIDIHDR */
3132 if (!lpMidiStrm
->dwStartTicks
)
3133 lpMidiStrm
->dwStartTicks
= GetTickCount();
3135 /* FIXME(EPP): "I don't understand the content of the first MIDIHDR sent
3136 * by native mcimidi, it doesn't look like a correct one".
3137 * this trick allows to throw it away... but I don't like it.
3138 * It looks like part of the file I'm trying to play and definitively looks
3139 * like raw midi content
3140 * I'd really like to understand why native mcimidi sends it. Perhaps a bad
3141 * synchronization issue where native mcimidi is still processing raw MIDI
3142 * content before generating MIDIEVENTs ?
3144 * 4c 04 89 3b 00 81 7c 99 3b 43 00 99 23 5e 04 89 L..;..|.;C..#^..
3145 * 3b 00 00 89 23 00 7c 99 3b 45 00 99 28 62 04 89 ;...#.|.;E..(b..
3146 * 3b 00 00 89 28 00 81 7c 99 3b 4e 00 99 23 5e 04 ;...(..|.;N..#^.
3147 * 89 3b 00 00 89 23 00 7c 99 3b 45 00 99 23 78 04 .;...#.|.;E..#x.
3148 * 89 3b 00 00 89 23 00 81 7c 99 3b 48 00 99 23 5e .;...#..|.;H..#^
3149 * 04 89 3b 00 00 89 23 00 7c 99 3b 4e 00 99 28 62 ..;...#.|.;N..(b
3150 * 04 89 3b 00 00 89 28 00 81 7c 99 39 4c 00 99 23 ..;...(..|.9L..#
3151 * 5e 04 89 39 00 00 89 23 00 82 7c 99 3b 4c 00 99 ^..9...#..|.;L..
3152 * 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b 48 00 99 #^..;...#.|.;H..
3153 * 28 62 04 89 3b 00 00 89 28 00 81 7c 99 3b 3f 04 (b..;...(..|.;?.
3154 * 89 3b 00 1c 99 23 5e 04 89 23 00 5c 99 3b 45 00 .;...#^..#.\.;E.
3155 * 99 23 78 04 89 3b 00 00 89 23 00 81 7c 99 3b 46 .#x..;...#..|.;F
3156 * 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b 48 ..#^..;...#.|.;H
3157 * 00 99 28 62 04 89 3b 00 00 89 28 00 81 7c 99 3b ..(b..;...(..|.;
3158 * 46 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b F..#^..;...#.|.;
3159 * 48 00 99 23 78 04 89 3b 00 00 89 23 00 81 7c 99 H..#x..;...#..|.
3160 * 3b 4c 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 ;L..#^..;...#.|.
3162 lpMidiHdr
= (LPMIDIHDR
)msg
->lParam
;
3163 lpData
= lpMidiHdr
->lpData
;
3164 TRACE("Adding %s lpMidiHdr=%p [lpData=0x%08lx dwBufferLength=%lu/%lu dwFlags=0x%08lx size=%u]\n",
3165 (lpMidiHdr
->dwFlags
& MHDR_ISSTRM
) ? "stream" : "regular", lpMidiHdr
,
3166 (DWORD
)lpMidiHdr
, lpMidiHdr
->dwBufferLength
, lpMidiHdr
->dwBytesRecorded
,
3167 lpMidiHdr
->dwFlags
, msg
->wParam
);
3169 /* dumps content of lpMidiHdr->lpData
3170 * FIXME: there should be a debug routine somewhere that already does this
3171 * I hate spreading this type of shit all around the code
3173 for (dwToGo
= 0; dwToGo
< lpMidiHdr
->dwBufferLength
; dwToGo
+= 16) {
3177 for (i
= 0; i
< min(16, lpMidiHdr
->dwBufferLength
- dwToGo
); i
++)
3178 printf("%02x ", lpData
[dwToGo
+ i
]);
3181 for (i
= 0; i
< min(16, lpMidiHdr
->dwBufferLength
- dwToGo
); i
++) {
3182 ch
= lpData
[dwToGo
+ i
];
3183 printf("%c", (ch
>= 0x20 && ch
<= 0x7F) ? ch
: '.');
3188 if (((LPMIDIEVENT
)lpData
)->dwStreamID
!= 0 &&
3189 ((LPMIDIEVENT
)lpData
)->dwStreamID
!= 0xFFFFFFFF &&
3190 ((LPMIDIEVENT
)lpData
)->dwStreamID
!= (DWORD
)lpMidiStrm
) {
3191 FIXME("Dropping bad %s lpMidiHdr (streamID=%08lx)\n",
3192 (lpMidiHdr
->dwFlags
& MHDR_ISSTRM
) ? "stream" : "regular",
3193 ((LPMIDIEVENT
)lpData
)->dwStreamID
);
3194 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
3195 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
3197 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
, lpMidiStrm
->hDevice
,
3198 MM_MOM_DONE
, lpwm
->mod
.dwInstance
, (DWORD
)lpMidiHdr
, 0L);
3202 for (lpmh
= &lpMidiStrm
->lpMidiHdr
; *lpmh
; lpmh
= (LPMIDIHDR
*)&((*lpmh
)->lpNext
));
3204 lpMidiHdr
= (LPMIDIHDR
)msg
->lParam
;
3205 lpMidiHdr
->lpNext
= 0;
3206 lpMidiHdr
->dwFlags
|= MHDR_INQUEUE
;
3207 lpMidiHdr
->dwFlags
&= MHDR_DONE
;
3208 lpMidiHdr
->dwOffset
= 0;
3212 FIXME("Unknown message %d\n", msg
->message
);
3218 /**************************************************************************
3219 * MMSYSTEM_MidiStream_Player [internal]
3221 static DWORD CALLBACK
MMSYSTEM_MidiStream_Player(LPVOID pmt
)
3223 WINE_MIDIStream
* lpMidiStrm
= pmt
;
3228 LPMIDIHDR lpMidiHdr
;
3232 TRACE("(%p)!\n", lpMidiStrm
);
3235 (lpwm
= (LPWINE_MIDI
)MMDRV_Get(lpMidiStrm
->hDevice
, MMDRV_MIDIOUT
, FALSE
)) == NULL
)
3238 /* force thread's queue creation */
3239 /* Used to be InitThreadInput16(0, 5); */
3240 /* but following works also with hack in midiStreamOpen */
3241 PeekMessageA(&msg
, 0, 0, 0, 0);
3243 /* FIXME: this next line must be called before midiStreamOut or midiStreamRestart are called */
3244 SetEvent(lpMidiStrm
->hEvent
);
3245 TRACE("Ready to go 1\n");
3246 /* thread is started in paused mode */
3247 SuspendThread(lpMidiStrm
->hThread
);
3248 TRACE("Ready to go 2\n");
3250 lpMidiStrm
->dwStartTicks
= 0;
3251 lpMidiStrm
->dwPulses
= 0;
3253 lpMidiStrm
->lpMidiHdr
= 0;
3256 lpMidiHdr
= lpMidiStrm
->lpMidiHdr
;
3258 /* for first message, block until one arrives, then process all that are available */
3259 GetMessageA(&msg
, 0, 0, 0);
3261 if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm
, lpwm
, &msg
))
3263 } while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
));
3269 lpData
= lpMidiHdr
->lpData
;
3271 me
= (LPMIDIEVENT
)(lpData
+ lpMidiHdr
->dwOffset
);
3273 /* do we have to wait ? */
3274 if (me
->dwDeltaTime
) {
3275 lpMidiStrm
->dwPositionMS
+= MMSYSTEM_MidiStream_Convert(lpMidiStrm
, me
->dwDeltaTime
);
3276 lpMidiStrm
->dwPulses
+= me
->dwDeltaTime
;
3278 dwToGo
= lpMidiStrm
->dwStartTicks
+ lpMidiStrm
->dwPositionMS
;
3280 TRACE("%ld/%ld/%ld\n", dwToGo
, GetTickCount(), me
->dwDeltaTime
);
3281 while ((dwCurrTC
= GetTickCount()) < dwToGo
) {
3282 if (MsgWaitForMultipleObjects(0, NULL
, FALSE
, dwToGo
- dwCurrTC
, QS_ALLINPUT
) == WAIT_OBJECT_0
) {
3283 /* got a message, handle it */
3284 while (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) {
3285 if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm
, lpwm
, &msg
))
3290 /* timeout, so me->dwDeltaTime is elapsed, can break the while loop */
3295 switch (MEVT_EVENTTYPE(me
->dwEvent
& ~MEVT_F_CALLBACK
)) {
3297 FIXME("NIY: MEVT_COMMENT\n");
3298 /* do nothing, skip bytes */
3301 FIXME("NIY: MEVT_LONGMSG, aka sending Sysex event\n");
3306 midiOutShortMsg(lpMidiStrm
->hDevice
, MEVT_EVENTPARM(me
->dwEvent
));
3309 lpMidiStrm
->dwTempo
= MEVT_EVENTPARM(me
->dwEvent
);
3314 FIXME("Unknown MEVT (0x%02x)\n", MEVT_EVENTTYPE(me
->dwEvent
& ~MEVT_F_CALLBACK
));
3317 if (me
->dwEvent
& MEVT_F_CALLBACK
) {
3318 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
, lpMidiStrm
->hDevice
,
3319 MM_MOM_POSITIONCB
, lpwm
->mod
.dwInstance
, (LPARAM
)lpMidiHdr
, 0L);
3321 lpMidiHdr
->dwOffset
+= sizeof(MIDIEVENT
) - sizeof(me
->dwParms
);
3322 if (me
->dwEvent
& MEVT_F_LONG
)
3323 lpMidiHdr
->dwOffset
+= (MEVT_EVENTPARM(me
->dwEvent
) + 3) & ~3;
3324 if (lpMidiHdr
->dwOffset
>= lpMidiHdr
->dwBufferLength
) {
3325 /* done with this header */
3326 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
3327 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
3329 lpMidiStrm
->lpMidiHdr
= (LPMIDIHDR
)lpMidiHdr
->lpNext
;
3330 DriverCallback(lpwm
->mod
.dwCallback
, lpMidiStrm
->wFlags
, lpMidiStrm
->hDevice
,
3331 MM_MOM_DONE
, lpwm
->mod
.dwInstance
, (DWORD
)lpMidiHdr
, 0L);
3336 TRACE("End of thread\n");
3338 return 0; /* for removing the warning, never executed */
3341 /**************************************************************************
3342 * MMSYSTEM_MidiStream_PostMessage [internal]
3344 static BOOL
MMSYSTEM_MidiStream_PostMessage(WINE_MIDIStream
* lpMidiStrm
, WORD msg
, DWORD pmt1
, DWORD pmt2
)
3346 if (PostThreadMessageA(lpMidiStrm
->dwThreadID
, msg
, pmt1
, pmt2
)) {
3349 ReleaseThunkLock(&count
);
3350 WaitForSingleObject(lpMidiStrm
->hEvent
, INFINITE
);
3351 RestoreThunkLock(count
);
3353 WARN("bad PostThreadMessageA\n");
3359 /**************************************************************************
3360 * midiStreamClose [WINMM.@]
3362 MMRESULT WINAPI
midiStreamClose(HMIDISTRM hMidiStrm
)
3364 WINE_MIDIStream
* lpMidiStrm
;
3366 TRACE("(%08x)!\n", hMidiStrm
);
3368 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
))
3369 return MMSYSERR_INVALHANDLE
;
3371 midiStreamStop(hMidiStrm
);
3372 MMSYSTEM_MidiStream_PostMessage(lpMidiStrm
, WM_QUIT
, 0, 0);
3373 HeapFree(GetProcessHeap(), 0, lpMidiStrm
);
3374 CloseHandle(lpMidiStrm
->hEvent
);
3376 return midiOutClose(hMidiStrm
);
3379 /**************************************************************************
3380 * MMSYSTEM_MidiStream_Open [internal]
3382 static MMRESULT WINAPI
MMSYSTEM_MidiStream_Open(HMIDISTRM
* lphMidiStrm
, LPUINT lpuDeviceID
,
3383 DWORD cMidi
, DWORD dwCallback
,
3384 DWORD dwInstance
, DWORD fdwOpen
, BOOL bFrom32
)
3386 WINE_MIDIStream
* lpMidiStrm
;
3388 MIDIOPENSTRMID mosm
;
3392 TRACE("(%p, %p, %ld, 0x%08lx, 0x%08lx, 0x%08lx)!\n",
3393 lphMidiStrm
, lpuDeviceID
, cMidi
, dwCallback
, dwInstance
, fdwOpen
);
3395 if (cMidi
!= 1 || lphMidiStrm
== NULL
|| lpuDeviceID
== NULL
)
3396 return MMSYSERR_INVALPARAM
;
3398 lpMidiStrm
= HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_MIDIStream
));
3400 return MMSYSERR_NOMEM
;
3402 lpMidiStrm
->dwTempo
= 500000;
3403 lpMidiStrm
->dwTimeDiv
= 480; /* 480 is 120 quater notes per minute *//* FIXME ??*/
3404 lpMidiStrm
->dwPositionMS
= 0;
3406 mosm
.dwStreamID
= (DWORD
)lpMidiStrm
;
3407 /* FIXME: the correct value is not allocated yet for MAPPER */
3408 mosm
.wDeviceID
= *lpuDeviceID
;
3409 lpwm
= MIDI_OutAlloc(&hMidiOut
, &dwCallback
, &dwInstance
, &fdwOpen
, 1, &mosm
, bFrom32
);
3410 lpMidiStrm
->hDevice
= hMidiOut
;
3412 *lphMidiStrm
= hMidiOut
;
3414 /* FIXME: is lpuDevice initialized upon entering midiStreamOpen ? */
3415 FIXME("*lpuDeviceID=%x\n", *lpuDeviceID
);
3416 lpwm
->mld
.uDeviceID
= *lpuDeviceID
= 0;
3418 ret
= MMDRV_Open(&lpwm
->mld
, MODM_OPEN
, (DWORD
)&lpwm
->mod
, fdwOpen
);
3419 lpMidiStrm
->hEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3420 lpMidiStrm
->wFlags
= HIWORD(fdwOpen
);
3422 lpMidiStrm
->hThread
= CreateThread(NULL
, 0, MMSYSTEM_MidiStream_Player
,
3423 lpMidiStrm
, 0, &(lpMidiStrm
->dwThreadID
));
3425 if (!lpMidiStrm
->hThread
) {
3426 midiStreamClose((HMIDISTRM
)hMidiOut
);
3427 return MMSYSERR_NOMEM
;
3430 /* wait for thread to have started, and for its queue to be created */
3434 /* (Release|Restore)ThunkLock() is needed when this method is called from 16 bit code,
3435 * (meaning the Win16Lock is set), so that it's released and the 32 bit thread running
3436 * MMSYSTEM_MidiStreamPlayer can acquire Win16Lock to create its queue.
3438 ReleaseThunkLock(&count
);
3439 WaitForSingleObject(lpMidiStrm
->hEvent
, INFINITE
);
3440 RestoreThunkLock(count
);
3443 TRACE("=> (%u/%d) hMidi=0x%04x ret=%d lpMidiStrm=%p\n",
3444 *lpuDeviceID
, lpwm
->mld
.uDeviceID
, *lphMidiStrm
, ret
, lpMidiStrm
);
3448 /**************************************************************************
3449 * midiStreamOpen [WINMM.@]
3451 MMRESULT WINAPI
midiStreamOpen(HMIDISTRM
* lphMidiStrm
, LPUINT lpuDeviceID
,
3452 DWORD cMidi
, DWORD dwCallback
,
3453 DWORD dwInstance
, DWORD fdwOpen
)
3455 return MMSYSTEM_MidiStream_Open(lphMidiStrm
, lpuDeviceID
, cMidi
, dwCallback
,
3456 dwInstance
, fdwOpen
, TRUE
);
3459 /**************************************************************************
3460 * midiStreamOut [WINMM.@]
3462 MMRESULT WINAPI
midiStreamOut(HMIDISTRM hMidiStrm
, LPMIDIHDR lpMidiHdr
,
3465 WINE_MIDIStream
* lpMidiStrm
;
3466 DWORD ret
= MMSYSERR_NOERROR
;
3468 TRACE("(%08x, %p, %u)!\n", hMidiStrm
, lpMidiHdr
, cbMidiHdr
);
3470 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3471 ret
= MMSYSERR_INVALHANDLE
;
3472 } else if (!lpMidiHdr
) {
3473 ret
= MMSYSERR_INVALPARAM
;
3475 if (!PostThreadMessageA(lpMidiStrm
->dwThreadID
,
3476 WINE_MSM_HEADER
, cbMidiHdr
,
3477 (DWORD
)lpMidiHdr
)) {
3478 WARN("bad PostThreadMessageA\n");
3479 ret
= MMSYSERR_ERROR
;
3485 /**************************************************************************
3486 * midiStreamPause [WINMM.@]
3488 MMRESULT WINAPI
midiStreamPause(HMIDISTRM hMidiStrm
)
3490 WINE_MIDIStream
* lpMidiStrm
;
3491 DWORD ret
= MMSYSERR_NOERROR
;
3493 TRACE("(%08x)!\n", hMidiStrm
);
3495 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3496 ret
= MMSYSERR_INVALHANDLE
;
3498 if (SuspendThread(lpMidiStrm
->hThread
) == 0xFFFFFFFF) {
3499 WARN("bad Suspend (%ld)\n", GetLastError());
3500 ret
= MMSYSERR_ERROR
;
3506 /**************************************************************************
3507 * midiStreamPosition [WINMM.@]
3509 MMRESULT WINAPI
midiStreamPosition(HMIDISTRM hMidiStrm
, LPMMTIME lpMMT
, UINT cbmmt
)
3511 WINE_MIDIStream
* lpMidiStrm
;
3512 DWORD ret
= MMSYSERR_NOERROR
;
3514 TRACE("(%08x, %p, %u)!\n", hMidiStrm
, lpMMT
, cbmmt
);
3516 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3517 ret
= MMSYSERR_INVALHANDLE
;
3518 } else if (lpMMT
== NULL
|| cbmmt
!= sizeof(MMTIME
)) {
3519 ret
= MMSYSERR_INVALPARAM
;
3521 switch (lpMMT
->wType
) {
3523 lpMMT
->u
.ms
= lpMidiStrm
->dwPositionMS
;
3524 TRACE("=> %ld ms\n", lpMMT
->u
.ms
);
3527 lpMMT
->u
.ticks
= lpMidiStrm
->dwPulses
;
3528 TRACE("=> %ld ticks\n", lpMMT
->u
.ticks
);
3531 WARN("Unsupported time type %d\n", lpMMT
->wType
);
3532 lpMMT
->wType
= TIME_MS
;
3533 ret
= MMSYSERR_INVALPARAM
;
3540 /**************************************************************************
3541 * midiStreamProperty [WINMM.@]
3543 MMRESULT WINAPI
midiStreamProperty(HMIDISTRM hMidiStrm
, LPBYTE lpPropData
, DWORD dwProperty
)
3545 WINE_MIDIStream
* lpMidiStrm
;
3546 MMRESULT ret
= MMSYSERR_NOERROR
;
3548 TRACE("(%08x, %p, %lx)\n", hMidiStrm
, lpPropData
, dwProperty
);
3550 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3551 ret
= MMSYSERR_INVALHANDLE
;
3552 } else if ((dwProperty
& (MIDIPROP_GET
|MIDIPROP_SET
)) == 0) {
3553 ret
= MMSYSERR_INVALPARAM
;
3554 } else if (dwProperty
& MIDIPROP_TEMPO
) {
3555 MIDIPROPTEMPO
* mpt
= (MIDIPROPTEMPO
*)lpPropData
;
3557 if (sizeof(MIDIPROPTEMPO
) != mpt
->cbStruct
) {
3558 ret
= MMSYSERR_INVALPARAM
;
3559 } else if (dwProperty
& MIDIPROP_SET
) {
3560 lpMidiStrm
->dwTempo
= mpt
->dwTempo
;
3561 TRACE("Setting tempo to %ld\n", mpt
->dwTempo
);
3562 } else if (dwProperty
& MIDIPROP_GET
) {
3563 mpt
->dwTempo
= lpMidiStrm
->dwTempo
;
3564 TRACE("Getting tempo <= %ld\n", mpt
->dwTempo
);
3566 } else if (dwProperty
& MIDIPROP_TIMEDIV
) {
3567 MIDIPROPTIMEDIV
* mptd
= (MIDIPROPTIMEDIV
*)lpPropData
;
3569 if (sizeof(MIDIPROPTIMEDIV
) != mptd
->cbStruct
) {
3570 ret
= MMSYSERR_INVALPARAM
;
3571 } else if (dwProperty
& MIDIPROP_SET
) {
3572 lpMidiStrm
->dwTimeDiv
= mptd
->dwTimeDiv
;
3573 TRACE("Setting time div to %ld\n", mptd
->dwTimeDiv
);
3574 } else if (dwProperty
& MIDIPROP_GET
) {
3575 mptd
->dwTimeDiv
= lpMidiStrm
->dwTimeDiv
;
3576 TRACE("Getting time div <= %ld\n", mptd
->dwTimeDiv
);
3579 ret
= MMSYSERR_INVALPARAM
;
3585 /**************************************************************************
3586 * midiStreamRestart [WINMM.@]
3588 MMRESULT WINAPI
midiStreamRestart(HMIDISTRM hMidiStrm
)
3590 WINE_MIDIStream
* lpMidiStrm
;
3591 MMRESULT ret
= MMSYSERR_NOERROR
;
3593 TRACE("(%08x)!\n", hMidiStrm
);
3595 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3596 ret
= MMSYSERR_INVALHANDLE
;
3600 /* since we increase the thread suspend count on each midiStreamPause
3601 * there may be a need for several midiStreamResume
3604 ret
= ResumeThread(lpMidiStrm
->hThread
);
3605 } while (ret
!= 0xFFFFFFFF && ret
!= 0);
3606 if (ret
== 0xFFFFFFFF) {
3607 WARN("bad Resume (%ld)\n", GetLastError());
3608 ret
= MMSYSERR_ERROR
;
3610 lpMidiStrm
->dwStartTicks
= GetTickCount() - lpMidiStrm
->dwPositionMS
;
3616 /**************************************************************************
3617 * midiStreamStop [WINMM.@]
3619 MMRESULT WINAPI
midiStreamStop(HMIDISTRM hMidiStrm
)
3621 WINE_MIDIStream
* lpMidiStrm
;
3622 MMRESULT ret
= MMSYSERR_NOERROR
;
3624 TRACE("(%08x)!\n", hMidiStrm
);
3626 if (!MMSYSTEM_GetMidiStream(hMidiStrm
, &lpMidiStrm
, NULL
)) {
3627 ret
= MMSYSERR_INVALHANDLE
;
3629 /* in case stream has been paused... FIXME is the current state correct ? */
3630 midiStreamRestart(hMidiStrm
);
3631 MMSYSTEM_MidiStream_PostMessage(lpMidiStrm
, WINE_MSM_STOP
, 0, 0);
3636 /**************************************************************************
3637 * midiStreamClose [MMSYSTEM.252]
3639 MMRESULT16 WINAPI
midiStreamClose16(HMIDISTRM16 hMidiStrm
)
3641 return midiStreamClose(hMidiStrm
);
3644 /**************************************************************************
3645 * midiStreamOpen [MMSYSTEM.251]
3647 MMRESULT16 WINAPI
midiStreamOpen16(HMIDISTRM16
* phMidiStrm
, LPUINT16 devid
,
3648 DWORD cMidi
, DWORD dwCallback
,
3649 DWORD dwInstance
, DWORD fdwOpen
)
3651 HMIDISTRM hMidiStrm32
;
3655 if (!phMidiStrm
|| !devid
)
3656 return MMSYSERR_INVALPARAM
;
3658 ret
= MMSYSTEM_MidiStream_Open(&hMidiStrm32
, &devid32
, cMidi
, dwCallback
,
3659 dwInstance
, fdwOpen
, FALSE
);
3660 *phMidiStrm
= hMidiStrm32
;
3665 /**************************************************************************
3666 * midiStreamOut [MMSYSTEM.254]
3668 MMRESULT16 WINAPI
midiStreamOut16(HMIDISTRM16 hMidiStrm
, LPMIDIHDR16 lpMidiHdr
, UINT16 cbMidiHdr
)
3670 return midiStreamOut(hMidiStrm
, (LPMIDIHDR
)lpMidiHdr
, cbMidiHdr
);
3673 /**************************************************************************
3674 * midiStreamPause [MMSYSTEM.255]
3676 MMRESULT16 WINAPI
midiStreamPause16(HMIDISTRM16 hMidiStrm
)
3678 return midiStreamPause(hMidiStrm
);
3681 /**************************************************************************
3682 * midiStreamPosition [MMSYSTEM.253]
3684 MMRESULT16 WINAPI
midiStreamPosition16(HMIDISTRM16 hMidiStrm
, LPMMTIME16 lpmmt16
, UINT16 cbmmt
)
3690 return MMSYSERR_INVALPARAM
;
3691 MMSYSTEM_MMTIME16to32(&mmt32
, lpmmt16
);
3692 ret
= midiStreamPosition(hMidiStrm
, &mmt32
, sizeof(MMTIME
));
3693 MMSYSTEM_MMTIME32to16(lpmmt16
, &mmt32
);
3697 /**************************************************************************
3698 * midiStreamProperty [MMSYSTEM.250]
3700 MMRESULT16 WINAPI
midiStreamProperty16(HMIDISTRM16 hMidiStrm
, LPBYTE lpPropData
, DWORD dwProperty
)
3702 return midiStreamProperty(hMidiStrm
, lpPropData
, dwProperty
);
3705 /**************************************************************************
3706 * midiStreamRestart [MMSYSTEM.256]
3708 MMRESULT16 WINAPI
midiStreamRestart16(HMIDISTRM16 hMidiStrm
)
3710 return midiStreamRestart(hMidiStrm
);
3713 /**************************************************************************
3714 * midiStreamStop [MMSYSTEM.257]
3716 MMRESULT16 WINAPI
midiStreamStop16(HMIDISTRM16 hMidiStrm
)
3718 return midiStreamStop(hMidiStrm
);
3721 static UINT WINAPI
MMSYSTEM_waveOpen(HANDLE
* lphndl
, UINT uDeviceID
, UINT uType
,
3722 const LPWAVEFORMATEX lpFormat
,
3723 DWORD dwCallback
, DWORD dwInstance
,
3724 DWORD dwFlags
, BOOL bFrom32
)
3728 DWORD dwRet
= MMSYSERR_NOERROR
;
3731 TRACE("(%p, %d, %s, %p, %08lX, %08lX, %08lX, %d);\n",
3732 lphndl
, (int)uDeviceID
, (uType
==MMDRV_WAVEOUT
)?"Out":"In", lpFormat
, dwCallback
,
3733 dwInstance
, dwFlags
, bFrom32
?32:16);
3735 if (dwFlags
& WAVE_FORMAT_QUERY
) TRACE("WAVE_FORMAT_QUERY requested !\n");
3737 if (lpFormat
== NULL
) return WAVERR_BADFORMAT
;
3738 if ((dwFlags
& WAVE_MAPPED
) && (uDeviceID
== (UINT
)-1))
3739 return MMSYSERR_INVALPARAM
;
3741 TRACE("wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u\n",
3742 lpFormat
->wFormatTag
, lpFormat
->nChannels
, lpFormat
->nSamplesPerSec
,
3743 lpFormat
->nAvgBytesPerSec
, lpFormat
->nBlockAlign
, lpFormat
->wBitsPerSample
, lpFormat
->cbSize
);
3745 if ((wmld
= MMDRV_Alloc(sizeof(WINE_WAVE
), uType
, &handle
,
3746 &dwFlags
, &dwCallback
, &dwInstance
, bFrom32
)) == NULL
)
3747 return MMSYSERR_NOMEM
;
3750 wod
.lpFormat
= lpFormat
; /* should the struct be copied iso pointer? */
3751 wod
.dwCallback
= dwCallback
;
3752 wod
.dwInstance
= dwInstance
;
3755 if (dwFlags
& WAVE_MAPPED
) {
3756 wod
.uMappedDeviceID
= uDeviceID
;
3757 uDeviceID
= WAVE_MAPPER
;
3759 wod
.uMappedDeviceID
= -1;
3761 wmld
->uDeviceID
= uDeviceID
;
3763 dwRet
= MMDRV_Open(wmld
, (uType
== MMDRV_WAVEOUT
) ? WODM_OPEN
: WIDM_OPEN
, (DWORD
)&wod
, dwFlags
);
3765 if ((dwFlags
& WAVE_FORMAT_QUERY
) || dwRet
!= MMSYSERR_NOERROR
) {
3766 MMDRV_Free(handle
, wmld
);
3770 if (lphndl
!= NULL
) *lphndl
= handle
;
3771 TRACE("=> %ld hWave=%04x\n", dwRet
, handle
);
3776 /**************************************************************************
3777 * waveOutGetNumDevs [WINMM.@]
3779 UINT WINAPI
waveOutGetNumDevs(void)
3781 return MMDRV_GetNum(MMDRV_WAVEOUT
);
3784 /**************************************************************************
3785 * waveOutGetNumDevs [MMSYSTEM.401]
3787 UINT16 WINAPI
waveOutGetNumDevs16(void)
3789 return MMDRV_GetNum(MMDRV_WAVEOUT
);
3792 /**************************************************************************
3793 * waveOutGetDevCaps [MMSYSTEM.402]
3795 UINT16 WINAPI
waveOutGetDevCaps16(UINT16 uDeviceID
,
3796 LPWAVEOUTCAPS16 lpCaps
, UINT16 uSize
)
3801 TRACE("(%u %p %u)!\n", uDeviceID
, lpCaps
, uSize
);
3802 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
3804 ret
= waveOutGetDevCapsA(uDeviceID
, &wocA
, sizeof(wocA
));
3806 if (ret
== MMSYSERR_NOERROR
) {
3807 lpCaps
->wMid
= wocA
.wMid
;
3808 lpCaps
->wPid
= wocA
.wPid
;
3809 lpCaps
->vDriverVersion
= wocA
.vDriverVersion
;
3810 strcpy(lpCaps
->szPname
, wocA
.szPname
);
3811 lpCaps
->dwFormats
= wocA
.dwFormats
;
3812 lpCaps
->wChannels
= wocA
.wChannels
;
3813 lpCaps
->dwSupport
= wocA
.dwSupport
;
3818 /**************************************************************************
3819 * waveOutGetDevCapsA [WINMM.@]
3821 UINT WINAPI
waveOutGetDevCapsA(UINT uDeviceID
, LPWAVEOUTCAPSA lpCaps
,
3826 TRACE("(%u %p %u)!\n", uDeviceID
, lpCaps
, uSize
);
3828 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
3830 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_WAVEOUT
, TRUE
)) == NULL
)
3831 return MMSYSERR_INVALHANDLE
;
3833 return MMDRV_Message(wmld
, WODM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
3837 /**************************************************************************
3838 * waveOutGetDevCapsW [WINMM.@]
3840 UINT WINAPI
waveOutGetDevCapsW(UINT uDeviceID
, LPWAVEOUTCAPSW lpCaps
,
3846 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
3848 ret
= waveOutGetDevCapsA(uDeviceID
, &wocA
, sizeof(wocA
));
3850 if (ret
== MMSYSERR_NOERROR
) {
3851 lpCaps
->wMid
= wocA
.wMid
;
3852 lpCaps
->wPid
= wocA
.wPid
;
3853 lpCaps
->vDriverVersion
= wocA
.vDriverVersion
;
3854 MultiByteToWideChar( CP_ACP
, 0, wocA
.szPname
, -1, lpCaps
->szPname
,
3855 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
3856 lpCaps
->dwFormats
= wocA
.dwFormats
;
3857 lpCaps
->wChannels
= wocA
.wChannels
;
3858 lpCaps
->dwSupport
= wocA
.dwSupport
;
3863 /**************************************************************************
3864 * WAVE_GetErrorText [internal]
3866 static UINT16
WAVE_GetErrorText(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
3868 UINT16 ret
= MMSYSERR_BADERRNUM
;
3870 if (lpText
== NULL
) {
3871 ret
= MMSYSERR_INVALPARAM
;
3872 } else if (uSize
== 0) {
3873 ret
= MMSYSERR_NOERROR
;
3875 /* test has been removed 'coz MMSYSERR_BASE is 0, and gcc did emit
3876 * a warning for the test was always true */
3877 (/*uError >= MMSYSERR_BASE && */uError
<= MMSYSERR_LASTERROR
) ||
3878 (uError
>= WAVERR_BASE
&& uError
<= WAVERR_LASTERROR
)) {
3880 if (LoadStringA(MULTIMEDIA_GetIData()->hWinMM32Instance
,
3881 uError
, lpText
, uSize
) > 0) {
3882 ret
= MMSYSERR_NOERROR
;
3888 /**************************************************************************
3889 * waveOutGetErrorText [MMSYSTEM.403]
3891 UINT16 WINAPI
waveOutGetErrorText16(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
3893 return WAVE_GetErrorText(uError
, lpText
, uSize
);
3896 /**************************************************************************
3897 * waveOutGetErrorTextA [WINMM.@]
3899 UINT WINAPI
waveOutGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
3901 return WAVE_GetErrorText(uError
, lpText
, uSize
);
3904 /**************************************************************************
3905 * waveOutGetErrorTextW [WINMM.@]
3907 UINT WINAPI
waveOutGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
3909 LPSTR xstr
= HeapAlloc(GetProcessHeap(), 0, uSize
);
3910 UINT ret
= WAVE_GetErrorText(uError
, xstr
, uSize
);
3912 MultiByteToWideChar( CP_ACP
, 0, xstr
, -1, lpText
, uSize
);
3913 HeapFree(GetProcessHeap(), 0, xstr
);
3917 /**************************************************************************
3918 * waveOutOpen [WINMM.@]
3919 * All the args/structs have the same layout as the win16 equivalents
3921 UINT WINAPI
waveOutOpen(HWAVEOUT
* lphWaveOut
, UINT uDeviceID
,
3922 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
3923 DWORD dwInstance
, DWORD dwFlags
)
3925 return MMSYSTEM_waveOpen(lphWaveOut
, uDeviceID
, MMDRV_WAVEOUT
, lpFormat
,
3926 dwCallback
, dwInstance
, dwFlags
, TRUE
);
3929 /**************************************************************************
3930 * waveOutOpen [MMSYSTEM.404]
3932 UINT16 WINAPI
waveOutOpen16(HWAVEOUT16
* lphWaveOut
, UINT16 uDeviceID
,
3933 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
3934 DWORD dwInstance
, DWORD dwFlags
)
3939 /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
3940 * call the 32 bit version
3941 * however, we need to promote correctly the wave mapper id
3942 * (0xFFFFFFFF and not 0x0000FFFF)
3944 ret
= MMSYSTEM_waveOpen(&hWaveOut
, (uDeviceID
== (UINT16
)-1) ? (UINT
)-1 : uDeviceID
,
3945 MMDRV_WAVEOUT
, lpFormat
, dwCallback
, dwInstance
, dwFlags
, FALSE
);
3947 if (lphWaveOut
!= NULL
) *lphWaveOut
= hWaveOut
;
3951 /**************************************************************************
3952 * waveOutClose [WINMM.@]
3954 UINT WINAPI
waveOutClose(HWAVEOUT hWaveOut
)
3959 TRACE("(%04X)\n", hWaveOut
);
3961 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
3962 return MMSYSERR_INVALHANDLE
;
3964 dwRet
= MMDRV_Close(wmld
, WODM_CLOSE
);
3965 MMDRV_Free(hWaveOut
, wmld
);
3970 /**************************************************************************
3971 * waveOutClose [MMSYSTEM.405]
3973 UINT16 WINAPI
waveOutClose16(HWAVEOUT16 hWaveOut
)
3978 ReleaseThunkLock(&level
);
3979 ret
= waveOutClose(hWaveOut
);
3980 RestoreThunkLock(level
);
3984 /**************************************************************************
3985 * waveOutPrepareHeader [WINMM.@]
3987 UINT WINAPI
waveOutPrepareHeader(HWAVEOUT hWaveOut
,
3988 WAVEHDR
* lpWaveOutHdr
, UINT uSize
)
3992 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpWaveOutHdr
, uSize
);
3994 if (lpWaveOutHdr
== NULL
) return MMSYSERR_INVALPARAM
;
3996 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
3997 return MMSYSERR_INVALHANDLE
;
3999 return MMDRV_Message(wmld
, WODM_PREPARE
, (DWORD
)lpWaveOutHdr
, uSize
, TRUE
);
4002 /**************************************************************************
4003 * waveOutPrepareHeader [MMSYSTEM.406]
4005 UINT16 WINAPI
waveOutPrepareHeader16(HWAVEOUT16 hWaveOut
, /* [in] */
4006 SEGPTR lpsegWaveOutHdr
, /* [???] */
4007 UINT16 uSize
) /* [in] */
4010 LPWAVEHDR lpWaveOutHdr
= MapSL(lpsegWaveOutHdr
);
4012 TRACE("(%04X, %08lx, %u);\n", hWaveOut
, lpsegWaveOutHdr
, uSize
);
4014 if (lpWaveOutHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4016 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4017 return MMSYSERR_INVALHANDLE
;
4019 return MMDRV_Message(wmld
, WODM_PREPARE
, (DWORD
)lpsegWaveOutHdr
, uSize
, FALSE
);
4022 /**************************************************************************
4023 * waveOutUnprepareHeader [WINMM.@]
4025 UINT WINAPI
waveOutUnprepareHeader(HWAVEOUT hWaveOut
,
4026 LPWAVEHDR lpWaveOutHdr
, UINT uSize
)
4030 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpWaveOutHdr
, uSize
);
4032 if (!(lpWaveOutHdr
->dwFlags
& WHDR_PREPARED
)) {
4033 return MMSYSERR_NOERROR
;
4036 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4037 return MMSYSERR_INVALHANDLE
;
4039 return MMDRV_Message(wmld
, WODM_UNPREPARE
, (DWORD
)lpWaveOutHdr
, uSize
, TRUE
);
4042 /**************************************************************************
4043 * waveOutUnprepareHeader [MMSYSTEM.407]
4045 UINT16 WINAPI
waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut
, /* [in] */
4046 SEGPTR lpsegWaveOutHdr
, /* [???] */
4047 UINT16 uSize
) /* [in] */
4050 LPWAVEHDR lpWaveOutHdr
= MapSL(lpsegWaveOutHdr
);
4052 TRACE("(%04X, %08lx, %u);\n", hWaveOut
, lpsegWaveOutHdr
, uSize
);
4054 if (!(lpWaveOutHdr
->dwFlags
& WHDR_PREPARED
)) {
4055 return MMSYSERR_NOERROR
;
4058 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4059 return MMSYSERR_INVALHANDLE
;
4061 return MMDRV_Message(wmld
, WODM_UNPREPARE
, (DWORD
)lpsegWaveOutHdr
, uSize
, FALSE
);
4064 /**************************************************************************
4065 * waveOutWrite [WINMM.@]
4067 UINT WINAPI
waveOutWrite(HWAVEOUT hWaveOut
, LPWAVEHDR lpWaveOutHdr
,
4072 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpWaveOutHdr
, uSize
);
4074 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4075 return MMSYSERR_INVALHANDLE
;
4077 return MMDRV_Message(wmld
, WODM_WRITE
, (DWORD
)lpWaveOutHdr
, uSize
, TRUE
);
4080 /**************************************************************************
4081 * waveOutWrite [MMSYSTEM.408]
4083 UINT16 WINAPI
waveOutWrite16(HWAVEOUT16 hWaveOut
, /* [in] */
4084 LPWAVEHDR lpsegWaveOutHdr
, /* [???] NOTE: SEGPTR */
4085 UINT16 uSize
) /* [in] */
4089 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpsegWaveOutHdr
, uSize
);
4091 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4092 return MMSYSERR_INVALHANDLE
;
4094 return MMDRV_Message(wmld
, WODM_WRITE
, (DWORD
)lpsegWaveOutHdr
, uSize
, FALSE
);
4097 /**************************************************************************
4098 * waveOutBreakLoop [WINMM.@]
4100 UINT WINAPI
waveOutBreakLoop(HWAVEOUT hWaveOut
)
4104 TRACE("(%04X);\n", hWaveOut
);
4106 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4107 return MMSYSERR_INVALHANDLE
;
4108 return MMDRV_Message(wmld
, WODM_BREAKLOOP
, 0L, 0L, TRUE
);
4111 /**************************************************************************
4112 * waveOutBreakLoop [MMSYSTEM.419]
4114 UINT16 WINAPI
waveOutBreakLoop16(HWAVEOUT16 hWaveOut16
)
4119 ReleaseThunkLock(&level
);
4120 ret
= waveOutBreakLoop(hWaveOut16
);
4121 RestoreThunkLock(level
);
4125 /**************************************************************************
4126 * waveOutPause [WINMM.@]
4128 UINT WINAPI
waveOutPause(HWAVEOUT hWaveOut
)
4132 TRACE("(%04X);\n", hWaveOut
);
4134 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4135 return MMSYSERR_INVALHANDLE
;
4136 return MMDRV_Message(wmld
, WODM_PAUSE
, 0L, 0L, TRUE
);
4139 /**************************************************************************
4140 * waveOutPause [MMSYSTEM.409]
4142 UINT16 WINAPI
waveOutPause16(HWAVEOUT16 hWaveOut16
)
4147 ReleaseThunkLock(&level
);
4148 ret
= waveOutPause(hWaveOut16
);
4149 RestoreThunkLock(level
);
4153 /**************************************************************************
4154 * waveOutReset [WINMM.@]
4156 UINT WINAPI
waveOutReset(HWAVEOUT hWaveOut
)
4160 TRACE("(%04X);\n", hWaveOut
);
4162 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4163 return MMSYSERR_INVALHANDLE
;
4164 return MMDRV_Message(wmld
, WODM_RESET
, 0L, 0L, TRUE
);
4167 /**************************************************************************
4168 * waveOutReset [MMSYSTEM.411]
4170 UINT16 WINAPI
waveOutReset16(HWAVEOUT16 hWaveOut16
)
4175 ReleaseThunkLock(&level
);
4176 ret
= waveOutReset(hWaveOut16
);
4177 RestoreThunkLock(level
);
4181 /**************************************************************************
4182 * waveOutRestart [WINMM.@]
4184 UINT WINAPI
waveOutRestart(HWAVEOUT hWaveOut
)
4188 TRACE("(%04X);\n", hWaveOut
);
4190 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4191 return MMSYSERR_INVALHANDLE
;
4192 return MMDRV_Message(wmld
, WODM_RESTART
, 0L, 0L, TRUE
);
4195 /**************************************************************************
4196 * waveOutRestart [MMSYSTEM.410]
4198 UINT16 WINAPI
waveOutRestart16(HWAVEOUT16 hWaveOut16
)
4203 ReleaseThunkLock(&level
);
4204 ret
= waveOutRestart(hWaveOut16
);
4205 RestoreThunkLock(level
);
4209 /**************************************************************************
4210 * waveOutGetPosition [WINMM.@]
4212 UINT WINAPI
waveOutGetPosition(HWAVEOUT hWaveOut
, LPMMTIME lpTime
,
4217 TRACE("(%04X, %p, %u);\n", hWaveOut
, lpTime
, uSize
);
4219 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4220 return MMSYSERR_INVALHANDLE
;
4222 return MMDRV_Message(wmld
, WODM_GETPOS
, (DWORD
)lpTime
, uSize
, TRUE
);
4225 /**************************************************************************
4226 * waveOutGetPosition [MMSYSTEM.412]
4228 UINT16 WINAPI
waveOutGetPosition16(HWAVEOUT16 hWaveOut
, LPMMTIME16 lpTime
,
4234 mmt
.wType
= lpTime
->wType
;
4235 ret
= waveOutGetPosition(hWaveOut
, &mmt
, sizeof(mmt
));
4236 MMSYSTEM_MMTIME32to16(lpTime
, &mmt
);
4240 /**************************************************************************
4241 * waveOutGetPitch [WINMM.@]
4243 UINT WINAPI
waveOutGetPitch(HWAVEOUT hWaveOut
, LPDWORD lpdw
)
4247 TRACE("(%04X, %08lx);\n", hWaveOut
, (DWORD
)lpdw
);
4249 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4250 return MMSYSERR_INVALHANDLE
;
4251 return MMDRV_Message(wmld
, WODM_GETPITCH
, (DWORD
)lpdw
, 0L, TRUE
);
4254 /**************************************************************************
4255 * waveOutGetPitch [MMSYSTEM.413]
4257 UINT16 WINAPI
waveOutGetPitch16(HWAVEOUT16 hWaveOut16
, LPDWORD lpdw
)
4259 return waveOutGetPitch(hWaveOut16
, lpdw
);
4262 /**************************************************************************
4263 * waveOutSetPitch [WINMM.@]
4265 UINT WINAPI
waveOutSetPitch(HWAVEOUT hWaveOut
, DWORD dw
)
4269 TRACE("(%04X, %08lx);\n", hWaveOut
, (DWORD
)dw
);
4271 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4272 return MMSYSERR_INVALHANDLE
;
4273 return MMDRV_Message(wmld
, WODM_SETPITCH
, dw
, 0L, TRUE
);
4276 /**************************************************************************
4277 * waveOutSetPitch [MMSYSTEM.414]
4279 UINT16 WINAPI
waveOutSetPitch16(HWAVEOUT16 hWaveOut16
, DWORD dw
)
4281 return waveOutSetPitch(hWaveOut16
, dw
);
4284 /**************************************************************************
4285 * waveOutGetPlaybackRate [WINMM.@]
4287 UINT WINAPI
waveOutGetPlaybackRate(HWAVEOUT hWaveOut
, LPDWORD lpdw
)
4291 TRACE("(%04X, %08lx);\n", hWaveOut
, (DWORD
)lpdw
);
4293 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4294 return MMSYSERR_INVALHANDLE
;
4295 return MMDRV_Message(wmld
, WODM_GETPLAYBACKRATE
, (DWORD
)lpdw
, 0L, TRUE
);
4298 /**************************************************************************
4299 * waveOutGetPlaybackRate [MMSYSTEM.417]
4301 UINT16 WINAPI
waveOutGetPlaybackRate16(HWAVEOUT16 hWaveOut16
, LPDWORD lpdw
)
4303 return waveOutGetPlaybackRate(hWaveOut16
, lpdw
);
4306 /**************************************************************************
4307 * waveOutSetPlaybackRate [WINMM.@]
4309 UINT WINAPI
waveOutSetPlaybackRate(HWAVEOUT hWaveOut
, DWORD dw
)
4313 TRACE("(%04X, %08lx);\n", hWaveOut
, (DWORD
)dw
);
4315 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4316 return MMSYSERR_INVALHANDLE
;
4317 return MMDRV_Message(wmld
, WODM_SETPLAYBACKRATE
, dw
, 0L, TRUE
);
4320 /**************************************************************************
4321 * waveOutSetPlaybackRate [MMSYSTEM.418]
4323 UINT16 WINAPI
waveOutSetPlaybackRate16(HWAVEOUT16 hWaveOut16
, DWORD dw
)
4325 return waveOutSetPlaybackRate(hWaveOut16
, dw
);
4328 /**************************************************************************
4329 * waveOutGetVolume [WINMM.@]
4331 UINT WINAPI
waveOutGetVolume(UINT devid
, LPDWORD lpdw
)
4335 TRACE("(%04X, %08lx);\n", devid
, (DWORD
)lpdw
);
4337 if ((wmld
= MMDRV_Get(devid
, MMDRV_WAVEOUT
, TRUE
)) == NULL
)
4338 return MMSYSERR_INVALHANDLE
;
4340 return MMDRV_Message(wmld
, WODM_GETVOLUME
, (DWORD
)lpdw
, 0L, TRUE
);
4343 /**************************************************************************
4344 * waveOutGetVolume [MMSYSTEM.415]
4346 UINT16 WINAPI
waveOutGetVolume16(UINT16 devid
, LPDWORD lpdw
)
4348 return waveOutGetVolume(devid
, lpdw
);
4351 /**************************************************************************
4352 * waveOutSetVolume [WINMM.@]
4354 UINT WINAPI
waveOutSetVolume(UINT devid
, DWORD dw
)
4358 TRACE("(%04X, %08lx);\n", devid
, dw
);
4360 if ((wmld
= MMDRV_Get(devid
, MMDRV_WAVEOUT
, TRUE
)) == NULL
)
4361 return MMSYSERR_INVALHANDLE
;
4363 return MMDRV_Message(wmld
, WODM_SETVOLUME
, dw
, 0L, TRUE
);
4366 /**************************************************************************
4367 * waveOutSetVolume [MMSYSTEM.416]
4369 UINT16 WINAPI
waveOutSetVolume16(UINT16 devid
, DWORD dw
)
4371 return waveOutSetVolume(devid
, dw
);
4374 /**************************************************************************
4375 * waveOutGetID [WINMM.@]
4377 UINT WINAPI
waveOutGetID(HWAVEOUT hWaveOut
, UINT
* lpuDeviceID
)
4381 TRACE("(%04X, %p);\n", hWaveOut
, lpuDeviceID
);
4383 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
4385 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4386 return MMSYSERR_INVALHANDLE
;
4388 *lpuDeviceID
= wmld
->uDeviceID
;
4392 /**************************************************************************
4393 * waveOutGetID [MMSYSTEM.420]
4395 UINT16 WINAPI
waveOutGetID16(HWAVEOUT16 hWaveOut
, UINT16
* lpuDeviceID
)
4399 TRACE("(%04X, %p);\n", hWaveOut
, lpuDeviceID
);
4401 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
4403 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
)
4404 return MMSYSERR_INVALHANDLE
;
4406 *lpuDeviceID
= wmld
->uDeviceID
;
4410 /**************************************************************************
4411 * waveOutMessage [WINMM.@]
4413 DWORD WINAPI
waveOutMessage(HWAVEOUT hWaveOut
, UINT uMessage
,
4414 DWORD dwParam1
, DWORD dwParam2
)
4418 TRACE("(%04x, %u, %ld, %ld)\n", hWaveOut
, uMessage
, dwParam1
, dwParam2
);
4420 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
) {
4421 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, TRUE
)) != NULL
) {
4422 return MMDRV_PhysicalFeatures(wmld
, uMessage
, dwParam1
, dwParam2
);
4424 return MMSYSERR_INVALHANDLE
;
4428 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
4429 return MMSYSERR_INVALPARAM
;
4431 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
4434 /**************************************************************************
4435 * waveOutMessage [MMSYSTEM.421]
4437 DWORD WINAPI
waveOutMessage16(HWAVEOUT16 hWaveOut
, UINT16 uMessage
,
4438 DWORD dwParam1
, DWORD dwParam2
)
4442 TRACE("(%04x, %u, %ld, %ld)\n", hWaveOut
, uMessage
, dwParam1
, dwParam2
);
4444 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, FALSE
)) == NULL
) {
4445 if ((wmld
= MMDRV_Get(hWaveOut
, MMDRV_WAVEOUT
, TRUE
)) != NULL
) {
4446 return MMDRV_PhysicalFeatures(wmld
, uMessage
, dwParam1
, dwParam2
);
4448 return MMSYSERR_INVALHANDLE
;
4452 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
4453 return MMSYSERR_INVALPARAM
;
4455 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, FALSE
);
4458 /**************************************************************************
4459 * waveInGetNumDevs [WINMM.@]
4461 UINT WINAPI
waveInGetNumDevs(void)
4463 return MMDRV_GetNum(MMDRV_WAVEIN
);
4466 /**************************************************************************
4467 * waveInGetNumDevs [MMSYSTEM.501]
4469 UINT16 WINAPI
waveInGetNumDevs16(void)
4471 return MMDRV_GetNum(MMDRV_WAVEIN
);
4474 /**************************************************************************
4475 * waveInGetDevCapsW [WINMM.@]
4477 UINT WINAPI
waveInGetDevCapsW(UINT uDeviceID
, LPWAVEINCAPSW lpCaps
, UINT uSize
)
4480 UINT ret
= waveInGetDevCapsA(uDeviceID
, &wicA
, uSize
);
4482 if (ret
== MMSYSERR_NOERROR
) {
4483 lpCaps
->wMid
= wicA
.wMid
;
4484 lpCaps
->wPid
= wicA
.wPid
;
4485 lpCaps
->vDriverVersion
= wicA
.vDriverVersion
;
4486 MultiByteToWideChar( CP_ACP
, 0, wicA
.szPname
, -1, lpCaps
->szPname
,
4487 sizeof(lpCaps
->szPname
)/sizeof(WCHAR
) );
4488 lpCaps
->dwFormats
= wicA
.dwFormats
;
4489 lpCaps
->wChannels
= wicA
.wChannels
;
4495 /**************************************************************************
4496 * waveInGetDevCapsA [WINMM.@]
4498 UINT WINAPI
waveInGetDevCapsA(UINT uDeviceID
, LPWAVEINCAPSA lpCaps
, UINT uSize
)
4502 TRACE("(%u %p %u)!\n", uDeviceID
, lpCaps
, uSize
);
4504 if ((wmld
= MMDRV_Get(uDeviceID
, MMDRV_WAVEIN
, TRUE
)) == NULL
)
4505 return MMSYSERR_INVALHANDLE
;
4507 return MMDRV_Message(wmld
, WIDM_GETDEVCAPS
, (DWORD
)lpCaps
, uSize
, TRUE
);
4510 /**************************************************************************
4511 * waveInGetDevCaps [MMSYSTEM.502]
4513 UINT16 WINAPI
waveInGetDevCaps16(UINT16 uDeviceID
, LPWAVEINCAPS16 lpCaps
,
4517 UINT ret
= waveInGetDevCapsA(uDeviceID
, &wicA
, sizeof(wicA
));
4519 if (lpCaps
== NULL
) return MMSYSERR_INVALPARAM
;
4521 if (ret
== MMSYSERR_NOERROR
) {
4522 lpCaps
->wMid
= wicA
.wMid
;
4523 lpCaps
->wPid
= wicA
.wPid
;
4524 lpCaps
->vDriverVersion
= wicA
.vDriverVersion
;
4525 strcpy(lpCaps
->szPname
, wicA
.szPname
);
4526 lpCaps
->dwFormats
= wicA
.dwFormats
;
4527 lpCaps
->wChannels
= wicA
.wChannels
;
4532 /**************************************************************************
4533 * waveInGetErrorTextA [WINMM.@]
4535 UINT WINAPI
waveInGetErrorTextA(UINT uError
, LPSTR lpText
, UINT uSize
)
4537 return WAVE_GetErrorText(uError
, lpText
, uSize
);
4540 /**************************************************************************
4541 * waveInGetErrorTextW [WINMM.@]
4543 UINT WINAPI
waveInGetErrorTextW(UINT uError
, LPWSTR lpText
, UINT uSize
)
4545 LPSTR txt
= HeapAlloc(GetProcessHeap(), 0, uSize
);
4546 UINT ret
= WAVE_GetErrorText(uError
, txt
, uSize
);
4548 MultiByteToWideChar( CP_ACP
, 0, txt
, -1, lpText
, uSize
);
4549 HeapFree(GetProcessHeap(), 0, txt
);
4553 /**************************************************************************
4554 * waveInGetErrorText [MMSYSTEM.503]
4556 UINT16 WINAPI
waveInGetErrorText16(UINT16 uError
, LPSTR lpText
, UINT16 uSize
)
4558 return WAVE_GetErrorText(uError
, lpText
, uSize
);
4561 /**************************************************************************
4562 * waveInOpen [WINMM.@]
4564 UINT WINAPI
waveInOpen(HWAVEIN
* lphWaveIn
, UINT uDeviceID
,
4565 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
4566 DWORD dwInstance
, DWORD dwFlags
)
4568 return MMSYSTEM_waveOpen(lphWaveIn
, uDeviceID
, MMDRV_WAVEIN
, lpFormat
,
4569 dwCallback
, dwInstance
, dwFlags
, TRUE
);
4572 /**************************************************************************
4573 * waveInOpen [MMSYSTEM.504]
4575 UINT16 WINAPI
waveInOpen16(HWAVEIN16
* lphWaveIn
, UINT16 uDeviceID
,
4576 const LPWAVEFORMATEX lpFormat
, DWORD dwCallback
,
4577 DWORD dwInstance
, DWORD dwFlags
)
4582 /* since layout of WAVEFORMATEX is the same for 16/32 bits, we directly
4583 * call the 32 bit version
4584 * however, we need to promote correctly the wave mapper id
4585 * (0xFFFFFFFF and not 0x0000FFFF)
4587 ret
= MMSYSTEM_waveOpen(&hWaveIn
, (uDeviceID
== (UINT16
)-1) ? (UINT
)-1 : uDeviceID
,
4588 MMDRV_WAVEIN
, lpFormat
, dwCallback
, dwInstance
, dwFlags
, FALSE
);
4590 if (lphWaveIn
!= NULL
) *lphWaveIn
= hWaveIn
;
4594 /**************************************************************************
4595 * waveInClose [WINMM.@]
4597 UINT WINAPI
waveInClose(HWAVEIN hWaveIn
)
4602 TRACE("(%04X)\n", hWaveIn
);
4604 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4605 return MMSYSERR_INVALHANDLE
;
4607 dwRet
= MMDRV_Message(wmld
, WIDM_CLOSE
, 0L, 0L, TRUE
);
4608 MMDRV_Free(hWaveIn
, wmld
);
4612 /**************************************************************************
4613 * waveInClose [MMSYSTEM.505]
4615 UINT16 WINAPI
waveInClose16(HWAVEIN16 hWaveIn
)
4620 ReleaseThunkLock(&level
);
4621 ret
= waveInClose(hWaveIn
);
4622 RestoreThunkLock(level
);
4626 /**************************************************************************
4627 * waveInPrepareHeader [WINMM.@]
4629 UINT WINAPI
waveInPrepareHeader(HWAVEIN hWaveIn
, WAVEHDR
* lpWaveInHdr
,
4634 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
4636 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4637 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4638 return MMSYSERR_INVALHANDLE
;
4640 lpWaveInHdr
->dwBytesRecorded
= 0;
4642 return MMDRV_Message(wmld
, WIDM_PREPARE
, (DWORD
)lpWaveInHdr
, uSize
, TRUE
);
4645 /**************************************************************************
4646 * waveInPrepareHeader [MMSYSTEM.506]
4648 UINT16 WINAPI
waveInPrepareHeader16(HWAVEIN16 hWaveIn
, /* [in] */
4649 SEGPTR lpsegWaveInHdr
, /* [???] */
4650 UINT16 uSize
) /* [in] */
4653 LPWAVEHDR lpWaveInHdr
= MapSL(lpsegWaveInHdr
);
4656 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
4658 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALHANDLE
;
4659 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4660 return MMSYSERR_INVALHANDLE
;
4662 lpWaveInHdr
->dwBytesRecorded
= 0;
4664 ret
= MMDRV_Message(wmld
, WIDM_PREPARE
, (DWORD
)lpsegWaveInHdr
, uSize
, FALSE
);
4668 /**************************************************************************
4669 * waveInUnprepareHeader [WINMM.@]
4671 UINT WINAPI
waveInUnprepareHeader(HWAVEIN hWaveIn
, WAVEHDR
* lpWaveInHdr
,
4676 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
4678 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4679 if (!(lpWaveInHdr
->dwFlags
& WHDR_PREPARED
)) {
4680 return MMSYSERR_NOERROR
;
4683 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4684 return MMSYSERR_INVALHANDLE
;
4686 return MMDRV_Message(wmld
, WIDM_UNPREPARE
, (DWORD
)lpWaveInHdr
, uSize
, TRUE
);
4689 /**************************************************************************
4690 * waveInUnprepareHeader [MMSYSTEM.507]
4692 UINT16 WINAPI
waveInUnprepareHeader16(HWAVEIN16 hWaveIn
, /* [in] */
4693 SEGPTR lpsegWaveInHdr
, /* [???] */
4694 UINT16 uSize
) /* [in] */
4697 LPWAVEHDR lpWaveInHdr
= MapSL(lpsegWaveInHdr
);
4699 TRACE("(%04X, %08lx, %u);\n", hWaveIn
, lpsegWaveInHdr
, uSize
);
4701 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4703 if (!(lpWaveInHdr
->dwFlags
& WHDR_PREPARED
)) {
4704 return MMSYSERR_NOERROR
;
4707 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4708 return MMSYSERR_INVALHANDLE
;
4710 return MMDRV_Message(wmld
, WIDM_UNPREPARE
, (DWORD
)lpsegWaveInHdr
, uSize
, FALSE
);
4713 /**************************************************************************
4714 * waveInAddBuffer [WINMM.@]
4716 UINT WINAPI
waveInAddBuffer(HWAVEIN hWaveIn
,
4717 WAVEHDR
* lpWaveInHdr
, UINT uSize
)
4721 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpWaveInHdr
, uSize
);
4723 if (lpWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4724 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4725 return MMSYSERR_INVALHANDLE
;
4727 return MMDRV_Message(wmld
, WIDM_ADDBUFFER
, (DWORD
)lpWaveInHdr
, uSize
, TRUE
);
4730 /**************************************************************************
4731 * waveInAddBuffer [MMSYSTEM.508]
4733 UINT16 WINAPI
waveInAddBuffer16(HWAVEIN16 hWaveIn
, /* [in] */
4734 WAVEHDR
* lpsegWaveInHdr
, /* [???] NOTE: SEGPTR */
4735 UINT16 uSize
) /* [in] */
4739 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpsegWaveInHdr
, uSize
);
4741 if (lpsegWaveInHdr
== NULL
) return MMSYSERR_INVALPARAM
;
4742 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4743 return MMSYSERR_INVALHANDLE
;
4745 return MMDRV_Message(wmld
, WIDM_ADDBUFFER
, (DWORD
)lpsegWaveInHdr
, uSize
, FALSE
);
4748 /**************************************************************************
4749 * waveInReset [WINMM.@]
4751 UINT WINAPI
waveInReset(HWAVEIN hWaveIn
)
4755 TRACE("(%04X);\n", hWaveIn
);
4757 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4758 return MMSYSERR_INVALHANDLE
;
4760 return MMDRV_Message(wmld
, WIDM_RESET
, 0L, 0L, TRUE
);
4763 /**************************************************************************
4764 * waveInReset [MMSYSTEM.511]
4766 UINT16 WINAPI
waveInReset16(HWAVEIN16 hWaveIn16
)
4771 ReleaseThunkLock(&level
);
4772 ret
= waveInReset(hWaveIn16
);
4773 RestoreThunkLock(level
);
4777 /**************************************************************************
4778 * waveInStart [WINMM.@]
4780 UINT WINAPI
waveInStart(HWAVEIN hWaveIn
)
4784 TRACE("(%04X);\n", hWaveIn
);
4786 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4787 return MMSYSERR_INVALHANDLE
;
4789 return MMDRV_Message(wmld
, WIDM_START
, 0L, 0L, TRUE
);
4792 /**************************************************************************
4793 * waveInStart [MMSYSTEM.509]
4795 UINT16 WINAPI
waveInStart16(HWAVEIN16 hWaveIn16
)
4800 ReleaseThunkLock(&level
);
4801 ret
= waveInStart(hWaveIn16
);
4802 RestoreThunkLock(level
);
4806 /**************************************************************************
4807 * waveInStop [WINMM.@]
4809 UINT WINAPI
waveInStop(HWAVEIN hWaveIn
)
4813 TRACE("(%04X);\n", hWaveIn
);
4815 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4816 return MMSYSERR_INVALHANDLE
;
4818 return MMDRV_Message(wmld
,WIDM_STOP
, 0L, 0L, TRUE
);
4821 /**************************************************************************
4822 * waveInStop [MMSYSTEM.510]
4824 UINT16 WINAPI
waveInStop16(HWAVEIN16 hWaveIn16
)
4829 ReleaseThunkLock(&level
);
4830 ret
= waveInStop(hWaveIn16
);
4831 RestoreThunkLock(level
);
4835 /**************************************************************************
4836 * waveInGetPosition [WINMM.@]
4838 UINT WINAPI
waveInGetPosition(HWAVEIN hWaveIn
, LPMMTIME lpTime
,
4843 TRACE("(%04X, %p, %u);\n", hWaveIn
, lpTime
, uSize
);
4845 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4846 return MMSYSERR_INVALHANDLE
;
4848 return MMDRV_Message(wmld
, WIDM_GETPOS
, (DWORD
)lpTime
, uSize
, TRUE
);
4851 /**************************************************************************
4852 * waveInGetPosition [MMSYSTEM.512]
4854 UINT16 WINAPI
waveInGetPosition16(HWAVEIN16 hWaveIn
, LPMMTIME16 lpTime
,
4860 mmt
.wType
= lpTime
->wType
;
4861 ret
= waveInGetPosition(hWaveIn
, &mmt
, sizeof(mmt
));
4862 MMSYSTEM_MMTIME32to16(lpTime
, &mmt
);
4866 /**************************************************************************
4867 * waveInGetID [WINMM.@]
4869 UINT WINAPI
waveInGetID(HWAVEIN hWaveIn
, UINT
* lpuDeviceID
)
4873 TRACE("(%04X, %p);\n", hWaveIn
, lpuDeviceID
);
4875 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
4877 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4878 return MMSYSERR_INVALHANDLE
;
4880 *lpuDeviceID
= wmld
->uDeviceID
;
4881 return MMSYSERR_NOERROR
;
4884 /**************************************************************************
4885 * waveInGetID [MMSYSTEM.513]
4887 UINT16 WINAPI
waveInGetID16(HWAVEIN16 hWaveIn
, UINT16
* lpuDeviceID
)
4891 TRACE("(%04X, %p);\n", hWaveIn
, lpuDeviceID
);
4893 if (lpuDeviceID
== NULL
) return MMSYSERR_INVALHANDLE
;
4895 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4896 return MMSYSERR_INVALHANDLE
;
4898 *lpuDeviceID
= wmld
->uDeviceID
;
4899 return MMSYSERR_NOERROR
;
4902 /**************************************************************************
4903 * waveInMessage [WINMM.@]
4905 DWORD WINAPI
waveInMessage(HWAVEIN hWaveIn
, UINT uMessage
,
4906 DWORD dwParam1
, DWORD dwParam2
)
4910 TRACE("(%04x, %u, %ld, %ld)\n", hWaveIn
, uMessage
, dwParam1
, dwParam2
);
4913 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
4914 return MMSYSERR_INVALPARAM
;
4916 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4917 return MMSYSERR_INVALHANDLE
;
4919 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
4922 /**************************************************************************
4923 * waveInMessage [MMSYSTEM.514]
4925 DWORD WINAPI
waveInMessage16(HWAVEIN16 hWaveIn
, UINT16 uMessage
,
4926 DWORD dwParam1
, DWORD dwParam2
)
4930 TRACE("(%04x, %u, %ld, %ld)\n", hWaveIn
, uMessage
, dwParam1
, dwParam2
);
4933 if (uMessage
< DRVM_IOCTL
|| (uMessage
>= DRVM_IOCTL_LAST
&& uMessage
< DRVM_MAPPER
))
4934 return MMSYSERR_INVALPARAM
;
4936 if ((wmld
= MMDRV_Get(hWaveIn
, MMDRV_WAVEIN
, FALSE
)) == NULL
)
4937 return MMSYSERR_INVALHANDLE
;
4939 return MMDRV_Message(wmld
, uMessage
, dwParam1
, dwParam2
, TRUE
);
4942 /*#define USE_MM_TSK_WINE*/
4944 /**************************************************************************
4945 * mmTaskCreate [MMSYSTEM.900]
4947 * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
4948 * called upon creation with dwPmt as parameter.
4950 HINSTANCE16 WINAPI
mmTaskCreate16(SEGPTR spProc
, HINSTANCE16
*lphMmTask
, DWORD dwPmt
)
4955 DWORD showCmd
= 0x40002;
4958 TRACE("(%08lx, %p, %08lx);\n", spProc
, lphMmTask
, dwPmt
);
4959 /* This to work requires NE modules to be started with a binary command line
4960 * which is not currently the case. A patch exists but has never been committed.
4961 * A workaround would be to integrate code for mmtask.tsk into Wine, but
4962 * this requires tremendous work (starting with patching tools/build to
4963 * create NE executables (and not only DLLs) for builtins modules.
4966 FIXME("This is currently broken. It will fail\n");
4969 *(LPDWORD
)(cmdline
+ 1) = (DWORD
)spProc
;
4970 *(LPDWORD
)(cmdline
+ 5) = dwPmt
;
4971 *(LPDWORD
)(cmdline
+ 9) = 0;
4973 lp
.hEnvironment
= 0;
4974 lp
.cmdLine
= MapLS(cmdline
);
4975 lp
.showCmd
= MapLS(&showCmd
);
4978 #ifndef USE_MM_TSK_WINE
4979 handle
= LoadModule16("c:\\windows\\system\\mmtask.tsk", &lp
);
4981 handle
= LoadModule16("mmtask.tsk", &lp
);
4984 ret
= (handle
) ? 1 : 2;
4990 *lphMmTask
= handle
;
4992 UnMapLS( lp
.cmdLine
);
4993 UnMapLS( lp
.showCmd
);
4994 TRACE("=> 0x%04x/%d\n", handle
, ret
);
4998 #ifdef USE_MM_TSK_WINE
4999 /* C equivalent to mmtask.tsk binary content */
5000 void mmTaskEntryPoint16(LPSTR cmdLine
, WORD di
, WORD si
)
5002 int len
= cmdLine
[0x80];
5005 void (*fpProc
)(DWORD
) = MapSL(*((DWORD
*)(cmdLine
+ 1)));
5006 DWORD dwPmt
= *((DWORD
*)(cmdLine
+ 5));
5009 InitTask16(); /* FIXME: pmts / from context ? */
5012 if (SetMessageQueue16(0x40)) {
5014 if (HIWORD(fpProc
)) {
5016 /* EPP StackEnter16(); */
5028 /**************************************************************************
5029 * mmTaskBlock [MMSYSTEM.902]
5031 void WINAPI
mmTaskBlock16(HINSTANCE16 WINE_UNUSED hInst
)
5036 GetMessageA(&msg
, 0, 0, 0);
5038 TranslateMessage(&msg
);
5039 DispatchMessageA(&msg
);
5041 } while (msg
.message
< 0x3A0);
5044 /**************************************************************************
5045 * mmTaskSignal [MMSYSTEM.903]
5047 LRESULT WINAPI
mmTaskSignal16(HTASK16 ht
)
5049 TRACE("(%04x);\n", ht
);
5050 return PostAppMessage16(ht
, WM_USER
, 0, 0);
5053 /**************************************************************************
5054 * mmGetCurrentTask [MMSYSTEM.904]
5056 HTASK16 WINAPI
mmGetCurrentTask16(void)
5058 return GetCurrentTask();
5061 /**************************************************************************
5062 * mmTaskYield [MMSYSTEM.905]
5064 void WINAPI
mmTaskYield16(void)
5068 if (PeekMessageA(&msg
, 0, 0, 0, 0)) {
5073 DWORD WINAPI
GetProcessFlags(DWORD
);
5075 /**************************************************************************
5076 * mmThreadCreate [MMSYSTEM.1120]
5079 * Creates a MM thread, calling fpThreadAddr(dwPmt).
5081 * bit.0 set means create a 16 bit task instead of thread calling a 16 bit proc
5082 * bit.1 set means to open a VxD for this thread (unsupported)
5084 LRESULT WINAPI
mmThreadCreate16(FARPROC16 fpThreadAddr
, LPHANDLE lpHndl
, DWORD dwPmt
, DWORD dwFlags
)
5089 TRACE("(%p, %p, %08lx, %08lx)!\n", fpThreadAddr
, lpHndl
, dwPmt
, dwFlags
);
5091 hndl
= GlobalAlloc16(sizeof(WINE_MMTHREAD
), GMEM_SHARE
|GMEM_ZEROINIT
);
5096 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5099 /* force mmtask routines even if mmthread is required */
5100 /* this will work only if the patch about binary cmd line and NE tasks
5106 lpMMThd
->dwSignature
= WINE_MMTHREAD_CREATED
;
5107 lpMMThd
->dwCounter
= 0;
5108 lpMMThd
->hThread
= 0;
5109 lpMMThd
->dwThreadID
= 0;
5110 lpMMThd
->fpThread
= fpThreadAddr
;
5111 lpMMThd
->dwThreadPmt
= dwPmt
;
5112 lpMMThd
->dwSignalCount
= 0;
5113 lpMMThd
->hEvent
= 0;
5115 lpMMThd
->dwStatus
= 0;
5116 lpMMThd
->dwFlags
= dwFlags
;
5119 if ((dwFlags
& 1) == 0 && (GetProcessFlags(GetCurrentThreadId()) & 8) == 0) {
5120 lpMMThd
->hEvent
= CreateEventA(0, 0, 1, 0);
5122 TRACE("Let's go crazy... trying new MM thread. lpMMThd=%p\n", lpMMThd
);
5123 if (lpMMThd
->dwFlags
& 2) {
5124 /* as long as we don't support MM VxD in wine, we don't need
5125 * to care about this flag
5127 /* FIXME("Don't know how to properly open VxD handles\n"); */
5128 /* lpMMThd->hVxD = OpenVxDHandle(lpMMThd->hEvent); */
5131 lpMMThd
->hThread
= CreateThread(0, 0, (LPTHREAD_START_ROUTINE
)WINE_mmThreadEntryPoint
,
5132 (LPVOID
)(DWORD
)hndl
, CREATE_SUSPENDED
, &lpMMThd
->dwThreadID
);
5133 if (lpMMThd
->hThread
== 0) {
5134 WARN("Couldn't create thread\n");
5135 /* clean-up(VxDhandle...); devicedirectio... */
5136 if (lpMMThd
->hEvent
!= 0)
5137 CloseHandle(lpMMThd
->hEvent
);
5140 TRACE("Got a nice thread hndl=0x%04x id=0x%08lx\n", lpMMThd
->hThread
, lpMMThd
->dwThreadID
);
5144 /* get WINE_mmThreadEntryPoint()
5145 * 2047 is its ordinal in mmsystem.spec
5147 FARPROC16 fp
= GetProcAddress16(GetModuleHandle16("MMSYSTEM"), (LPCSTR
)2047);
5149 TRACE("farproc seg=0x%08lx lin=%p\n", (DWORD
)fp
, MapSL((SEGPTR
)fp
));
5151 ret
= (fp
== 0) ? 2 : mmTaskCreate16((DWORD
)fp
, 0, hndl
);
5155 if (lpMMThd
->hThread
&& !ResumeThread(lpMMThd
->hThread
))
5156 WARN("Couldn't resume thread\n");
5158 while (lpMMThd
->dwStatus
!= 0x10) { /* test also HIWORD of dwStatus */
5172 TRACE("ok => %ld\n", ret
);
5176 /**************************************************************************
5177 * mmThreadSignal [MMSYSTEM.1121]
5179 void WINAPI
mmThreadSignal16(HANDLE16 hndl
)
5181 TRACE("(%04x)!\n", hndl
);
5184 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5186 lpMMThd
->dwCounter
++;
5187 if (lpMMThd
->hThread
!= 0) {
5188 InterlockedIncrement(&lpMMThd
->dwSignalCount
);
5189 SetEvent(lpMMThd
->hEvent
);
5191 mmTaskSignal16(lpMMThd
->hTask
);
5193 lpMMThd
->dwCounter
--;
5197 /**************************************************************************
5198 * MMSYSTEM_ThreadBlock [internal]
5200 static void MMSYSTEM_ThreadBlock(WINE_MMTHREAD
* lpMMThd
)
5205 if (lpMMThd
->dwThreadID
!= GetCurrentThreadId())
5206 ERR("Not called by thread itself\n");
5209 ResetEvent(lpMMThd
->hEvent
);
5210 if (InterlockedDecrement(&lpMMThd
->dwSignalCount
) >= 0)
5212 InterlockedIncrement(&lpMMThd
->dwSignalCount
);
5216 ret
= MsgWaitForMultipleObjects(1, &lpMMThd
->hEvent
, FALSE
, INFINITE
, QS_ALLINPUT
);
5218 case WAIT_OBJECT_0
: /* Event */
5221 case WAIT_OBJECT_0
+ 1: /* Msg */
5223 if (PeekMessageA(&msg
, 0, 0, 0, PM_REMOVE
)) {
5224 TranslateMessage(&msg
);
5225 DispatchMessageA(&msg
);
5229 WARN("S2.x unsupported ret val 0x%08lx\n", ret
);
5235 /**************************************************************************
5236 * mmThreadBlock [MMSYSTEM.1122]
5238 void WINAPI
mmThreadBlock16(HANDLE16 hndl
)
5240 TRACE("(%04x)!\n", hndl
);
5243 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5245 if (lpMMThd
->hThread
!= 0) {
5248 ReleaseThunkLock(&lc
);
5249 MMSYSTEM_ThreadBlock(lpMMThd
);
5250 RestoreThunkLock(lc
);
5252 mmTaskBlock16(lpMMThd
->hTask
);
5258 /**************************************************************************
5259 * mmThreadIsCurrent [MMSYSTEM.1123]
5261 BOOL16 WINAPI
mmThreadIsCurrent16(HANDLE16 hndl
)
5265 TRACE("(%04x)!\n", hndl
);
5267 if (hndl
&& mmThreadIsValid16(hndl
)) {
5268 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5269 ret
= (GetCurrentThreadId() == lpMMThd
->dwThreadID
);
5271 TRACE("=> %d\n", ret
);
5275 /**************************************************************************
5276 * mmThreadIsValid [MMSYSTEM.1124]
5278 BOOL16 WINAPI
mmThreadIsValid16(HANDLE16 hndl
)
5282 TRACE("(%04x)!\n", hndl
);
5285 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5287 if (!IsBadWritePtr(lpMMThd
, sizeof(WINE_MMTHREAD
)) &&
5288 lpMMThd
->dwSignature
== WINE_MMTHREAD_CREATED
&&
5289 IsTask16(lpMMThd
->hTask
)) {
5290 lpMMThd
->dwCounter
++;
5291 if (lpMMThd
->hThread
!= 0) {
5293 if (GetExitCodeThread(lpMMThd
->hThread
, &dwThreadRet
) &&
5294 dwThreadRet
== STATUS_PENDING
) {
5300 lpMMThd
->dwCounter
--;
5303 TRACE("=> %d\n", ret
);
5307 /**************************************************************************
5308 * mmThreadGetTask [MMSYSTEM.1125]
5310 HANDLE16 WINAPI
mmThreadGetTask16(HANDLE16 hndl
)
5314 TRACE("(%04x)\n", hndl
);
5316 if (mmThreadIsValid16(hndl
)) {
5317 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5318 ret
= lpMMThd
->hTask
;
5323 /* ### start build ### */
5324 extern LONG CALLBACK
MMSYSTEM_CallTo16_long_l (FARPROC16
,LONG
);
5325 /* ### stop build ### */
5327 /**************************************************************************
5328 * __wine_mmThreadEntryPoint (MMSYSTEM.2047)
5330 void WINAPI
WINE_mmThreadEntryPoint(DWORD _pmt
)
5332 HANDLE16 hndl
= (HANDLE16
)_pmt
;
5333 WINE_MMTHREAD
* lpMMThd
= MapSL( MAKESEGPTR(hndl
, 0) );
5335 TRACE("(%04x %p)\n", hndl
, lpMMThd
);
5337 lpMMThd
->hTask
= LOWORD(GetCurrentTask());
5338 TRACE("[10-%08x] setting hTask to 0x%08x\n", lpMMThd
->hThread
, lpMMThd
->hTask
);
5339 lpMMThd
->dwStatus
= 0x10;
5340 MMSYSTEM_ThreadBlock(lpMMThd
);
5341 TRACE("[20-%08x]\n", lpMMThd
->hThread
);
5342 lpMMThd
->dwStatus
= 0x20;
5343 if (lpMMThd
->fpThread
) {
5344 MMSYSTEM_CallTo16_long_l(lpMMThd
->fpThread
, lpMMThd
->dwThreadPmt
);
5346 lpMMThd
->dwStatus
= 0x30;
5347 TRACE("[30-%08x]\n", lpMMThd
->hThread
);
5348 while (lpMMThd
->dwCounter
) {
5350 /* K32WOWYield16();*/
5352 TRACE("[XX-%08x]\n", lpMMThd
->hThread
);
5354 lpMMThd
->dwSignature
= WINE_MMTHREAD_DELETED
;
5355 /* close lpMMThread->hVxD directIO */
5356 if (lpMMThd
->hEvent
)
5357 CloseHandle(lpMMThd
->hEvent
);
5362 typedef BOOL16 (WINAPI
*MMCPLCALLBACK
)(HWND
, LPCSTR
, LPCSTR
, LPCSTR
);
5364 /**************************************************************************
5365 * mmShowMMCPLPropertySheet [MMSYSTEM.1150]
5367 BOOL16 WINAPI
mmShowMMCPLPropertySheet16(HWND hWnd
, LPCSTR lpStrDevice
,
5368 LPCSTR lpStrTab
, LPCSTR lpStrTitle
)
5373 TRACE("(%04x \"%s\" \"%s\" \"%s\")\n", hWnd
, lpStrDevice
, lpStrTab
, lpStrTitle
);
5375 hndl
= LoadLibraryA("MMSYS.CPL");
5377 MMCPLCALLBACK fp
= (MMCPLCALLBACK
)GetProcAddress(hndl
, "ShowMMCPLPropertySheet");
5380 ReleaseThunkLock(&lc
);
5381 ret
= (fp
)(hWnd
, lpStrDevice
, lpStrTab
, lpStrTitle
);
5382 RestoreThunkLock(lc
);
5390 /**************************************************************************
5391 * StackEnter [MMSYSTEM.32]
5393 void WINAPI
StackEnter16(void)
5396 /* mmsystem.dll from Win 95 does only this: so does Wine */
5401 /**************************************************************************
5402 * StackLeave [MMSYSTEM.33]
5404 void WINAPI
StackLeave16(void)
5407 /* mmsystem.dll from Win 95 does only this: so does Wine */
5412 /**************************************************************************
5413 * WMMMidiRunOnce [MMSYSTEM.8]
5415 void WINAPI
WMMMidiRunOnce16(void)
5417 FIXME("(), stub!\n");
5420 /**************************************************************************
5421 * OutputDebugStr [MMSYSTEM.30]
5423 void WINAPI
OutputDebugStr16(
5424 LPCSTR str
) /* [in] The message to be logged and given to the debugger. */
5426 OutputDebugStringA( str
);