Authors: Chris Morgan <cmorgan@wpi.edu>, James Abbatiello <abbeyj@wpi.edu>
[wine/wine-kai.git] / multimedia / mmsystem.c
blob40adb0108fc403a5485e6c7c2e3f8885fcc20fbd
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 /*
4 * MMSYTEM functions
6 * Copyright 1993 Martin Ayotte
7 */
9 /*
10 * Eric POUECH :
11 * 98/9 added support for Win32 MCI
14 /* FIXME: I think there are some segmented vs. linear pointer weirdnesses
15 * and long term pointers to 16 bit space in here
18 #include <stdlib.h>
19 #include <string.h>
20 #include <fcntl.h>
21 #include <errno.h>
22 #include <sys/ioctl.h>
24 #include "winbase.h"
25 #include "windef.h"
26 #include "wine/winbase16.h"
27 #include "heap.h"
28 #include "user.h"
29 #include "driver.h"
30 #include "multimedia.h"
31 #include "callback.h"
32 #include "module.h"
33 #include "selectors.h"
34 #include "debugstr.h"
35 #include "debug.h"
37 UINT16 WINAPI midiGetErrorText(UINT16 uError, LPSTR lpText, UINT16 uSize);
38 static UINT16 waveGetErrorText(UINT16 uError, LPSTR lpText, UINT16 uSize);
39 LONG WINAPI DrvDefDriverProc(DWORD dwDevID, HDRVR16 hDrv, WORD wMsg,
40 DWORD dwParam1, DWORD dwParam2);
42 /**************************************************************************
43 * MMSYSTEM_WEP [MMSYSTEM.1]
45 int WINAPI MMSYSTEM_WEP(HINSTANCE16 hInstance, WORD wDataSeg,
46 WORD cbHeapSize, LPSTR lpCmdLine)
48 FIXME(mmsys, "STUB: Unloading MMSystem DLL ... hInst=%04X \n", hInstance);
49 return(TRUE);
52 static void MMSYSTEM_MMTIME32to16(LPMMTIME16 mmt16, LPMMTIME mmt32)
54 mmt16->wType = mmt32->wType;
55 /* layout of rest is the same for 32/16 */
56 memcpy(&(mmt32->u), &(mmt16->u), sizeof(mmt16->u));
59 static void MMSYSTEM_MMTIME16to32(LPMMTIME mmt32, LPMMTIME16 mmt16)
61 mmt32->wType = mmt16->wType;
62 /* layout of rest is the same for 32/16,
63 * Note: mmt16->u is 2 bytes smaller than mmt32->u
65 memcpy(&(mmt16->u), &(mmt32->u), sizeof(mmt16->u));
68 static HANDLE PlaySound_hThread = 0;
69 static HANDLE PlaySound_hPlayEvent = 0;
70 static HANDLE PlaySound_hReadyEvent = 0;
71 static HANDLE PlaySound_hMiddleEvent = 0;
72 static BOOL PlaySound_Result = FALSE;
73 static int PlaySound_Stop = FALSE;
74 static int PlaySound_Playing = FALSE;
76 static LPCSTR PlaySound_pszSound = NULL;
77 static HMODULE PlaySound_hmod = 0;
78 static DWORD PlaySound_fdwSound = 0;
79 static int PlaySound_Loop = FALSE;
80 static int PlaySound_SearchMode = 0; /* 1 - sndPlaySound search order
81 2 - PlaySound order */
83 static HMMIO16 get_mmioFromFile(LPCSTR lpszName)
85 return mmioOpen16((LPSTR)lpszName, NULL,
86 MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
89 static HMMIO16 get_mmioFromProfile(UINT uFlags, LPCSTR lpszName)
91 char str[128];
92 LPSTR ptr;
93 HMMIO16 hmmio;
95 TRACE(mmsys, "searching in SystemSound List !\n");
96 GetProfileStringA("Sounds", (LPSTR)lpszName, "", str, sizeof(str));
97 if (strlen(str) == 0) {
98 if (uFlags & SND_NODEFAULT) return 0;
99 GetProfileStringA("Sounds", "Default", "", str, sizeof(str));
100 if (strlen(str) == 0) return 0;
102 if ((ptr = (LPSTR)strchr(str, ',')) != NULL) *ptr = '\0';
103 hmmio = get_mmioFromFile(str);
104 if (hmmio == 0) {
105 WARN(mmsys, "can't find SystemSound='%s' !\n", str);
106 return 0;
108 return hmmio;
111 static BOOL16 WINAPI proc_PlaySound(LPCSTR lpszSoundName, UINT uFlags)
113 BOOL16 bRet = FALSE;
114 HMMIO16 hmmio;
115 MMCKINFO ckMainRIFF;
117 TRACE(mmsys, "SoundName='%s' uFlags=%04X !\n", lpszSoundName, uFlags);
118 if (lpszSoundName == NULL) {
119 TRACE(mmsys, "Stop !\n");
120 return FALSE;
122 if (uFlags & SND_MEMORY) {
123 MMIOINFO16 mminfo;
124 memset(&mminfo, 0, sizeof(mminfo));
125 mminfo.fccIOProc = FOURCC_MEM;
126 mminfo.pchBuffer = (LPSTR)lpszSoundName;
127 mminfo.cchBuffer = -1;
128 TRACE(mmsys, "Memory sound %p\n", lpszSoundName);
129 hmmio = mmioOpen16(NULL, &mminfo, MMIO_READ);
130 } else {
131 hmmio = 0;
132 if (uFlags & SND_ALIAS)
133 if ((hmmio=get_mmioFromProfile(uFlags, lpszSoundName)) == 0)
134 return FALSE;
136 if (uFlags & SND_FILENAME)
137 if ((hmmio=get_mmioFromFile(lpszSoundName)) == 0) return FALSE;
139 if (PlaySound_SearchMode == 1) {
140 PlaySound_SearchMode = 0;
141 if ((hmmio=get_mmioFromFile(lpszSoundName)) == 0)
142 if ((hmmio=get_mmioFromProfile(uFlags, lpszSoundName)) == 0)
143 return FALSE;
146 if (PlaySound_SearchMode == 2) {
147 PlaySound_SearchMode = 0;
148 if ((hmmio=get_mmioFromProfile(uFlags | SND_NODEFAULT, lpszSoundName)) == 0)
149 if ((hmmio=get_mmioFromFile(lpszSoundName)) == 0)
150 if ((hmmio=get_mmioFromProfile(uFlags, lpszSoundName)) == 0) return FALSE;
154 if (mmioDescend(hmmio, &ckMainRIFF, NULL, 0) == 0)
155 do {
156 TRACE(mmsys, "ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
157 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
158 ckMainRIFF.cksize);
160 if ((ckMainRIFF.ckid == FOURCC_RIFF) &&
161 (ckMainRIFF.fccType == mmioFOURCC('W', 'A', 'V', 'E'))) {
162 MMCKINFO mmckInfo;
164 mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
166 if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) == 0) {
167 PCMWAVEFORMAT pcmWaveFormat;
169 TRACE(mmsys, "Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
170 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType, mmckInfo.cksize);
172 if (mmioRead(hmmio, (HPSTR)&pcmWaveFormat,
173 (long) sizeof(PCMWAVEFORMAT)) == (long) sizeof(PCMWAVEFORMAT)) {
174 TRACE(mmsys, "wFormatTag=%04X !\n", pcmWaveFormat.wf.wFormatTag);
175 TRACE(mmsys, "nChannels=%d \n", pcmWaveFormat.wf.nChannels);
176 TRACE(mmsys, "nSamplesPerSec=%ld\n", pcmWaveFormat.wf.nSamplesPerSec);
177 TRACE(mmsys, "nAvgBytesPerSec=%ld\n", pcmWaveFormat.wf.nAvgBytesPerSec);
178 TRACE(mmsys, "nBlockAlign=%d \n", pcmWaveFormat.wf.nBlockAlign);
179 TRACE(mmsys, "wBitsPerSample=%u !\n", pcmWaveFormat.wBitsPerSample);
181 mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
182 if (mmioDescend(hmmio, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) == 0) {
183 WAVEOPENDESC waveDesc;
184 DWORD dwRet;
186 TRACE(mmsys, "Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX\n",
187 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType, mmckInfo.cksize);
189 pcmWaveFormat.wf.nAvgBytesPerSec = pcmWaveFormat.wf.nSamplesPerSec *
190 pcmWaveFormat.wf.nBlockAlign;
191 waveDesc.hWave = 0;
192 waveDesc.lpFormat = (LPWAVEFORMAT)&pcmWaveFormat;
194 dwRet = wodMessage(0, WODM_OPEN, 0, (DWORD)&waveDesc, CALLBACK_NULL);
195 if (dwRet == MMSYSERR_NOERROR) {
196 WAVEHDR waveHdr;
197 HGLOBAL16 hData;
198 INT count, bufsize, left = mmckInfo.cksize;
200 bufsize = 64000;
201 hData = GlobalAlloc16(GMEM_MOVEABLE, bufsize);
202 waveHdr.lpData = (LPSTR)GlobalLock16(hData);
203 waveHdr.dwBufferLength = bufsize;
204 waveHdr.dwUser = 0L;
205 waveHdr.dwFlags = 0L;
206 waveHdr.dwLoops = 0L;
208 dwRet = wodMessage(0, WODM_PREPARE, 0, (DWORD)&waveHdr, sizeof(WAVEHDR));
209 if (dwRet == MMSYSERR_NOERROR) {
210 while (left) {
211 if (PlaySound_Stop) {
212 PlaySound_Stop = FALSE;
213 PlaySound_Loop = FALSE;
214 break;
216 if (bufsize > left) bufsize = left;
217 count = mmioRead(hmmio, waveHdr.lpData,bufsize);
218 if (count < 1) break;
219 left -= count;
220 waveHdr.dwBufferLength = count;
221 /* waveHdr.dwBytesRecorded = count; */
222 /* FIXME: doesn't expect async ops */
223 wodMessage(0, WODM_WRITE, 0, (DWORD)&waveHdr, sizeof(WAVEHDR));
225 wodMessage(0, WODM_UNPREPARE, 0, (DWORD)&waveHdr, sizeof(WAVEHDR));
226 wodMessage(0, WODM_CLOSE, 0, 0L, 0L);
228 bRet = TRUE;
229 } else
230 WARN(mmsys, "can't prepare WaveOut device !\n");
232 GlobalUnlock16(hData);
233 GlobalFree16(hData);
239 } while (PlaySound_Loop);
241 if (hmmio != 0) mmioClose(hmmio, 0);
242 return bRet;
245 static DWORD WINAPI PlaySound_Thread(LPVOID arg)
247 DWORD res;
249 for (;;) {
250 PlaySound_Playing = FALSE;
251 SetEvent(PlaySound_hReadyEvent);
252 res = WaitForSingleObject(PlaySound_hPlayEvent, INFINITE);
253 ResetEvent(PlaySound_hReadyEvent);
254 SetEvent(PlaySound_hMiddleEvent);
255 if (res == WAIT_FAILED) ExitThread(2);
256 if (res != WAIT_OBJECT_0) continue;
257 PlaySound_Playing = TRUE;
259 if ((PlaySound_fdwSound & SND_RESOURCE) == SND_RESOURCE) {
260 HRSRC hRES;
261 HGLOBAL hGLOB;
262 void* ptr;
264 if ((hRES = FindResourceA(PlaySound_hmod, PlaySound_pszSound, "WAVE")) == 0) {
265 PlaySound_Result = FALSE;
266 continue;
268 if ((hGLOB = LoadResource(PlaySound_hmod, hRES)) == 0) {
269 PlaySound_Result = FALSE;
270 continue;
272 if ((ptr = LockResource(hGLOB)) == NULL) {
273 FreeResource(hGLOB);
274 PlaySound_Result = FALSE;
275 continue;
277 PlaySound_Result = proc_PlaySound(ptr,
278 ((UINT16)PlaySound_fdwSound ^ SND_RESOURCE) | SND_MEMORY);
279 FreeResource(hGLOB);
280 continue;
282 PlaySound_Result=proc_PlaySound(PlaySound_pszSound, (UINT16)PlaySound_fdwSound);
286 /**************************************************************************
287 * PlaySoundA [WINMM.1]
289 BOOL WINAPI PlaySoundA(LPCSTR pszSound, HMODULE hmod, DWORD fdwSound)
291 static LPSTR StrDup = NULL;
293 TRACE(mmsys, "pszSound='%p' hmod=%04X fdwSound=%08lX\n",
294 pszSound, hmod, fdwSound);
296 if (PlaySound_hThread == 0) { /* This is the first time they called us */
297 DWORD id;
298 if ((PlaySound_hReadyEvent = CreateEventA(NULL, TRUE, FALSE, NULL)) == 0)
299 return FALSE;
300 if ((PlaySound_hMiddleEvent = CreateEventA(NULL, FALSE, FALSE, NULL)) == 0)
301 return FALSE;
302 if ((PlaySound_hPlayEvent = CreateEventA(NULL, FALSE, FALSE, NULL)) == 0)
303 return FALSE;
304 if ((PlaySound_hThread = CreateThread(NULL, 0, PlaySound_Thread, 0, 0, &id)) == 0)
305 return FALSE;
308 /* FIXME? I see no difference between SND_WAIT and SND_NOSTOP ! */
309 if ((fdwSound & (SND_NOWAIT | SND_NOSTOP)) && PlaySound_Playing)
310 return FALSE;
312 /* Trying to stop if playing */
313 if (PlaySound_Playing) PlaySound_Stop = TRUE;
315 /* Waiting playing thread to get ready. I think 10 secs is ok & if not then leave*/
316 if (WaitForSingleObject(PlaySound_hReadyEvent, 1000*10) != WAIT_OBJECT_0)
317 return FALSE;
319 if (!pszSound || (fdwSound & SND_PURGE))
320 return FALSE; /* We stoped playing so leaving */
322 if (PlaySound_SearchMode != 1) PlaySound_SearchMode = 2;
323 if (!(fdwSound & SND_ASYNC)) {
324 if (fdwSound & SND_LOOP)
325 return FALSE;
326 PlaySound_pszSound = pszSound;
327 PlaySound_hmod = hmod;
328 PlaySound_fdwSound = fdwSound;
329 PlaySound_Result = FALSE;
330 SetEvent(PlaySound_hPlayEvent);
331 if (WaitForSingleObject(PlaySound_hMiddleEvent, INFINITE) != WAIT_OBJECT_0)
332 return FALSE;
333 if (WaitForSingleObject(PlaySound_hReadyEvent, INFINITE) != WAIT_OBJECT_0)
334 return FALSE;
335 return PlaySound_Result;
336 } else {
337 PlaySound_hmod = hmod;
338 PlaySound_fdwSound = fdwSound;
339 PlaySound_Result = FALSE;
340 if (StrDup) {
341 HeapFree(GetProcessHeap(), 0, StrDup);
342 StrDup = NULL;
344 if (!((fdwSound & SND_MEMORY) || ((fdwSound & SND_RESOURCE) &&
345 !((DWORD)pszSound >> 16)) || !pszSound)) {
346 StrDup = HEAP_strdupA(GetProcessHeap(), 0,pszSound);
347 PlaySound_pszSound = StrDup;
348 } else PlaySound_pszSound = pszSound;
349 PlaySound_Loop = fdwSound & SND_LOOP;
350 SetEvent(PlaySound_hPlayEvent);
351 ResetEvent(PlaySound_hMiddleEvent);
352 return TRUE;
354 return FALSE;
357 /**************************************************************************
358 * PlaySoundW [WINMM.18]
360 BOOL WINAPI PlaySoundW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
362 LPSTR pszSoundA;
363 BOOL bSound;
365 if (!((fdwSound & SND_MEMORY) || ((fdwSound & SND_RESOURCE) &&
366 !((DWORD)pszSound >> 16)) || !pszSound)) {
367 pszSoundA = HEAP_strdupWtoA(GetProcessHeap(), 0,pszSound);
368 bSound = PlaySoundA(pszSoundA, hmod, fdwSound);
369 HeapFree(GetProcessHeap(), 0,pszSoundA);
370 } else
371 bSound = PlaySoundA((LPCSTR)pszSound, hmod, fdwSound);
373 return bSound;
376 /**************************************************************************
377 * sndPlaySoundA [MMSYSTEM.2][WINMM135]
379 BOOL16 WINAPI sndPlaySoundA(LPCSTR lpszSoundName, UINT16 uFlags)
381 PlaySound_SearchMode = 1;
382 return PlaySoundA(lpszSoundName, 0, uFlags);
385 /**************************************************************************
386 * sndPlaySoundW [WINMM.136]
388 BOOL16 WINAPI sndPlaySoundW(LPCWSTR lpszSoundName, UINT16 uFlags)
390 PlaySound_SearchMode = 1;
391 return PlaySoundW(lpszSoundName, 0, uFlags);
394 /**************************************************************************
395 * mmsystemGetVersion [WINMM.134]
397 UINT WINAPI mmsystemGetVersion()
399 return mmsystemGetVersion16();
402 /**************************************************************************
403 * mmsystemGetVersion [MMSYSTEM.5]
404 * return value borrowed from Win95 winmm.dll ;)
406 UINT16 WINAPI mmsystemGetVersion16()
408 TRACE(mmsys, "3.10 (Win95?)\n");
409 return 0x030a;
412 /**************************************************************************
413 * DriverProc [MMSYSTEM.6]
415 LRESULT WINAPI DriverProc16(DWORD dwDevID, HDRVR16 hDrv, WORD wMsg,
416 DWORD dwParam1, DWORD dwParam2)
418 return DrvDefDriverProc(dwDevID, hDrv, wMsg, dwParam1, dwParam2);
421 /**************************************************************************
422 * DriverCallback [MMSYSTEM.31]
424 BOOL16 WINAPI DriverCallback16(DWORD dwCallBack, UINT16 uFlags, HANDLE16 hDev,
425 WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
427 TRACE(mmsys, "(%08lX, %04X, %04X, %04X, %08lX, %08lX, %08lX); !\n",
428 dwCallBack, uFlags, hDev, wMsg, dwUser, dwParam1, dwParam2);
430 switch (uFlags & DCB_TYPEMASK) {
431 case DCB_NULL:
432 TRACE(mmsys, "CALLBACK_NULL !\n");
433 break;
434 case DCB_WINDOW:
435 TRACE(mmsys, "CALLBACK_WINDOW = %04lX handle = %04X!\n",
436 dwCallBack, hDev);
437 if (!IsWindow(dwCallBack) || USER_HEAP_LIN_ADDR(hDev) == NULL)
438 return FALSE;
440 PostMessageA((HWND16)dwCallBack, wMsg, hDev, dwParam1);
441 break;
442 case DCB_TASK:
443 TRACE(mmsys, "CALLBACK_TASK !\n");
444 return FALSE;
445 case DCB_FUNCTION:
446 TRACE(mmsys, "CALLBACK_FUNCTION !\n");
447 Callbacks->CallDriverCallback((FARPROC16)dwCallBack,
448 hDev, wMsg, dwUser,
449 dwParam1, dwParam2 );
450 break;
451 case DCB_FUNC32:
452 TRACE(mmsys, "CALLBACK_FUNCTION !\n");
453 ((LPDRVCALLBACK)dwCallBack)(hDev, wMsg, dwUser,
454 dwParam1, dwParam2 );
455 break;
456 default:
457 WARN(mmsys, "Unknown callback type\n");
458 break;
460 return TRUE;
463 /**************************************************************************
464 * Mixer devices. New to Win95
467 /**************************************************************************
468 * find out the real mixer ID depending on hmix (depends on dwFlags)
469 * FIXME: also fix dwInstance passing to mixMessage
471 static UINT MIXER_GetDevID(HMIXEROBJ hmix, DWORD dwFlags)
473 /* FIXME: Check dwFlags for MIXER_OBJSECTF_xxxx entries and modify hmix
474 * accordingly. For now we always use mixerdevice 0.
476 return 0;
479 /**************************************************************************
480 * mixerGetNumDevs [WINMM.108]
482 UINT WINAPI mixerGetNumDevs(void)
484 UINT16 count = mixMessage(0, MXDM_GETNUMDEVS, 0L, 0L, 0L);
486 TRACE(mmaux,"mixerGetNumDevs returns %d\n",count);
487 return count;
490 /**************************************************************************
491 * mixerGetNumDevs [MMSYSTEM.800]
493 UINT16 WINAPI mixerGetNumDevs16()
495 return mixerGetNumDevs();
498 /**************************************************************************
499 * mixerGetDevCapsA [WINMM.101]
501 UINT WINAPI mixerGetDevCapsA(UINT devid, LPMIXERCAPSA mixcaps, UINT size)
503 return mixMessage(devid, MXDM_GETDEVCAPS, 0L, (DWORD)mixcaps, (DWORD)size);
506 /**************************************************************************
507 * mixerGetDevCapsW [WINMM.102]
509 UINT WINAPI mixerGetDevCapsW(UINT devid, LPMIXERCAPSW mixcaps, UINT size)
511 MIXERCAPSA micA;
512 UINT ret = mixerGetDevCapsA(devid, &micA, sizeof(micA));
514 if (ret == MMSYSERR_NOERROR) {
515 mixcaps->wMid = micA.wMid;
516 mixcaps->wPid = micA.wPid;
517 mixcaps->vDriverVersion = micA.vDriverVersion;
518 lstrcpyAtoW(mixcaps->szPname, micA.szPname);
519 mixcaps->fdwSupport = micA.fdwSupport;
520 mixcaps->cDestinations = micA.cDestinations;
522 return ret;
525 /**************************************************************************
526 * mixerGetDevCaps [MMSYSTEM.801]
528 UINT16 WINAPI mixerGetDevCaps16(UINT16 devid, LPMIXERCAPS16 mixcaps, UINT16 size)
530 MIXERCAPSA micA;
531 UINT ret = mixerGetDevCapsA(devid, &micA, sizeof(micA));
533 if (ret == MMSYSERR_NOERROR) {
534 mixcaps->wMid = micA.wMid;
535 mixcaps->wPid = micA.wPid;
536 mixcaps->vDriverVersion = micA.vDriverVersion;
537 strcpy(PTR_SEG_TO_LIN(mixcaps->szPname), micA.szPname);
538 mixcaps->fdwSupport = micA.fdwSupport;
539 mixcaps->cDestinations = micA.cDestinations;
541 return ret;
544 /**************************************************************************
545 * mixerOpen [WINMM.110]
547 UINT WINAPI mixerOpen(LPHMIXER lphmix, UINT uDeviceID, DWORD dwCallback,
548 DWORD dwInstance, DWORD fdwOpen)
550 HMIXER16 hmix16;
551 UINT ret;
553 FIXME(mmsys,"(%p,%d,%08lx,%08lx,%08lx): semi stub?\n",
554 lphmix,uDeviceID, dwCallback, dwInstance, fdwOpen);
555 ret = mixerOpen16(&hmix16,uDeviceID, dwCallback, dwInstance,fdwOpen);
556 if (lphmix) *lphmix = hmix16;
557 return ret;
560 /**************************************************************************
561 * mixerOpen [MMSYSTEM.803]
563 UINT16 WINAPI mixerOpen16(LPHMIXER16 lphmix, UINT16 uDeviceID, DWORD dwCallback,
564 DWORD dwInstance, DWORD fdwOpen)
566 HMIXER16 hmix;
567 LPMIXEROPENDESC lpmod;
568 BOOL mapperflag = (uDeviceID==0);
569 DWORD dwRet=0;
571 TRACE(mmsys,"(%p,%d,%08lx,%08lx,%08lx)\n",
572 lphmix,uDeviceID, dwCallback, dwInstance, fdwOpen);
573 hmix = USER_HEAP_ALLOC(sizeof(MIXEROPENDESC));
574 if (lphmix) *lphmix = hmix;
575 lpmod = (LPMIXEROPENDESC)USER_HEAP_LIN_ADDR(hmix);
576 lpmod->hmx = hmix;
577 lpmod->dwCallback = dwCallback;
578 lpmod->dwInstance = dwInstance;
579 if (uDeviceID >= MAXMIXERDRIVERS)
580 uDeviceID = 0;
581 while (uDeviceID < MAXMIXERDRIVERS) {
582 dwRet = mixMessage(uDeviceID, MXDM_OPEN, dwInstance, (DWORD)lpmod, fdwOpen);
583 if (dwRet == MMSYSERR_NOERROR) break;
584 if (!mapperflag) break;
585 uDeviceID++;
587 lpmod->uDeviceID = uDeviceID;
588 return dwRet;
591 /**************************************************************************
592 * mixerClose [WINMM.98]
594 UINT WINAPI mixerClose(HMIXER hmix)
596 LPMIXEROPENDESC lpmod;
598 FIXME(mmsys,"(%04x): semi-stub?\n", hmix);
600 lpmod = (LPMIXEROPENDESC)USER_HEAP_LIN_ADDR(hmix);
601 return mixMessage(lpmod->uDeviceID, MXDM_CLOSE, lpmod->dwInstance, 0L, 0L);
604 /**************************************************************************
605 * mixerClose [MMSYSTEM.803]
607 UINT16 WINAPI mixerClose16(HMIXER16 hmix)
609 return mixerClose(hmix);
612 /**************************************************************************
613 * mixerGetID [WINMM.103]
615 UINT WINAPI mixerGetID(HMIXEROBJ hmix, LPUINT lpid, DWORD fdwID)
617 FIXME(mmsys,"(%04x %p %08lx): semi-stub\n", hmix, lpid, fdwID);
619 if (lpid)
620 *lpid = MIXER_GetDevID(hmix, fdwID);
622 return MMSYSERR_NOERROR; /* FIXME: many error possibilities */
625 /**************************************************************************
626 * mixerGetID
628 UINT16 WINAPI mixerGetID16(HMIXEROBJ16 hmix, LPUINT16 lpid, DWORD fdwID)
630 UINT xid;
631 UINT ret = mixerGetID(hmix, &xid, fdwID);
633 if (lpid)
634 *lpid = xid;
635 return ret;
638 /**************************************************************************
639 * mixerGetControlDetailsA [WINMM.99]
641 UINT WINAPI mixerGetControlDetailsA(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails)
643 FIXME(mmsys,"(%04x,%p,%08lx): stub!\n", hmix, lpmcd, fdwDetails);
644 return MMSYSERR_NOTENABLED;
647 /**************************************************************************
648 * mixerGetControlDetailsW [WINMM.100]
650 UINT WINAPI mixerGetControlDetailsW(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails)
652 FIXME(mmsys,"(%04x,%p,%08lx): stub!\n", hmix, lpmcd, fdwDetails);
653 return MMSYSERR_NOTENABLED;
656 /**************************************************************************
657 * mixerGetControlDetails [MMSYSTEM.808]
659 UINT16 WINAPI mixerGetControlDetails16(HMIXEROBJ16 hmix, LPMIXERCONTROLDETAILS16 lpmcd, DWORD fdwDetails)
661 FIXME(mmsys,"(%04x,%p,%08lx): stub!\n", hmix, lpmcd, fdwDetails);
662 return MMSYSERR_NOTENABLED;
665 /**************************************************************************
666 * mixerGetLineControlsA [WINMM.104]
668 UINT WINAPI mixerGetLineControlsA(HMIXEROBJ hmix, LPMIXERLINECONTROLSA lpmlc, DWORD fdwControls)
670 UINT uDevID;
672 FIXME(mmsys,"(%04x,%p,%08lx): stub!\n", hmix, lpmlc, fdwControls);
674 uDevID = MIXER_GetDevID(hmix, 0);
676 return mixMessage(uDevID, MXDM_GETLINECONTROLS, 0, (DWORD)lpmlc, fdwControls);
679 /**************************************************************************
680 * mixerGetLineControlsW [WINMM.105]
682 UINT WINAPI mixerGetLineControlsW(HMIXEROBJ hmix, LPMIXERLINECONTROLSW lpmlc, DWORD fdwControls)
684 FIXME(mmsys,"(%04x,%p,%08lx): stub!\n", hmix, lpmlc, fdwControls);
685 return MMSYSERR_NOTENABLED;
688 /**************************************************************************
689 * mixerGetLineControls [MMSYSTEM.807]
691 UINT16 WINAPI mixerGetLineControls16(HMIXEROBJ16 hmix, LPMIXERLINECONTROLS16 lpmlc, DWORD fdwControls)
693 FIXME(mmsys,"(%04x,%p,%08lx): stub!\n", hmix, lpmlc, fdwControls);
694 return MMSYSERR_NOTENABLED;
697 /**************************************************************************
698 * mixerGetLineInfoA [WINMM.106]
700 UINT WINAPI mixerGetLineInfoA(HMIXEROBJ hmix, LPMIXERLINEA lpml, DWORD fdwInfo)
702 UINT16 devid;
704 TRACE(mmsys, "(%04x, %p, %08lx)\n", hmix, lpml, fdwInfo);
706 /* FIXME: I'm not sure of the flags */
707 devid = MIXER_GetDevID(hmix, fdwInfo);
708 return mixMessage(devid, MXDM_GETLINEINFO, 0, (DWORD)lpml, fdwInfo);
711 /**************************************************************************
712 * mixerGetLineInfoW [WINMM.107]
714 UINT WINAPI mixerGetLineInfoW(HMIXEROBJ hmix, LPMIXERLINEW lpml, DWORD fdwInfo)
716 MIXERLINEA mlA;
717 UINT ret;
719 TRACE(mmsys,"(%04x,%p,%08lx)\n", hmix, lpml, fdwInfo);
721 if (lpml == NULL || lpml->cbStruct != sizeof(*lpml))
722 return MMSYSERR_INVALPARAM;
724 mlA.cbStruct = sizeof(mlA);
725 mlA.dwDestination = lpml->dwDestination;
726 mlA.dwSource = lpml->dwSource;
727 mlA.dwLineID = lpml->dwLineID;
728 mlA.dwUser = lpml->dwUser;
729 mlA.dwComponentType = lpml->dwComponentType;
730 mlA.cChannels = lpml->cChannels;
731 mlA.cConnections = lpml->cConnections;
732 mlA.cControls = lpml->cControls;
734 ret = mixerGetLineInfoA(hmix, &mlA, fdwInfo);
736 lpml->dwDestination = mlA.dwDestination;
737 lpml->dwSource = mlA.dwSource;
738 lpml->dwLineID = mlA.dwLineID;
739 lpml->fdwLine = mlA.fdwLine;
740 lpml->dwUser = mlA.dwUser;
741 lpml->dwComponentType = mlA.dwComponentType;
742 lpml->cChannels = mlA.cChannels;
743 lpml->cConnections = mlA.cConnections;
744 lpml->cControls = mlA.cControls;
745 lstrcpyAtoW(lpml->szShortName, mlA.szShortName);
746 lstrcpyAtoW(lpml->szName, mlA.szName);
747 lpml->Target.dwType = mlA.Target.dwType;
748 lpml->Target.dwDeviceID = mlA.Target.dwDeviceID;
749 lpml->Target.wMid = mlA.Target.wMid;
750 lpml->Target.wPid = mlA.Target.wPid;
751 lpml->Target.vDriverVersion = mlA.Target.vDriverVersion;
752 lstrcpyAtoW(lpml->Target.szPname, mlA.Target.szPname);
754 return ret;
757 /**************************************************************************
758 * mixerGetLineInfo [MMSYSTEM.805]
760 UINT16 WINAPI mixerGetLineInfo16(HMIXEROBJ16 hmix, LPMIXERLINE16 lpml, DWORD fdwInfo)
762 MIXERLINEA mlA;
763 UINT ret;
765 TRACE(mmsys, "(%04x,%p,%08lx)\n", hmix, lpml, fdwInfo);
767 if (lpml == NULL || lpml->cbStruct != sizeof(*lpml))
768 return MMSYSERR_INVALPARAM;
770 mlA.cbStruct = sizeof(mlA);
771 mlA.dwDestination = lpml->dwDestination;
772 mlA.dwSource = lpml->dwSource;
773 mlA.dwLineID = lpml->dwLineID;
774 mlA.dwUser = lpml->dwUser;
775 mlA.dwComponentType = lpml->dwComponentType;
776 mlA.cChannels = lpml->cChannels;
777 mlA.cConnections = lpml->cConnections;
778 mlA.cControls = lpml->cControls;
780 ret = mixerGetLineInfoA(hmix, &mlA, fdwInfo);
782 lpml->dwDestination = mlA.dwDestination;
783 lpml->dwSource = mlA.dwSource;
784 lpml->dwLineID = mlA.dwLineID;
785 lpml->fdwLine = mlA.fdwLine;
786 lpml->dwUser = mlA.dwUser;
787 lpml->dwComponentType = mlA.dwComponentType;
788 lpml->cChannels = mlA.cChannels;
789 lpml->cConnections = mlA.cConnections;
790 lpml->cControls = mlA.cControls;
791 strcpy(PTR_SEG_TO_LIN(lpml->szShortName), mlA.szShortName);
792 strcpy(PTR_SEG_TO_LIN(lpml->szName), mlA.szName);
793 lpml->Target.dwType = mlA.Target.dwType;
794 lpml->Target.dwDeviceID = mlA.Target.dwDeviceID;
795 lpml->Target.wMid = mlA.Target.wMid;
796 lpml->Target.wPid = mlA.Target.wPid;
797 lpml->Target.vDriverVersion = mlA.Target.vDriverVersion;
798 strcpy(PTR_SEG_TO_LIN(lpml->Target.szPname), mlA.Target.szPname);
799 return ret;
802 /**************************************************************************
803 * mixerSetControlDetails [WINMM.111]
805 UINT WINAPI mixerSetControlDetails(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcd, DWORD fdwDetails)
807 FIXME(mmsys,"(%04x,%p,%08lx): stub!\n", hmix, lpmcd, fdwDetails);
808 return MMSYSERR_NOTENABLED;
811 /**************************************************************************
812 * mixerSetControlDetails [MMSYSTEM.809]
814 UINT16 WINAPI mixerSetControlDetails16(HMIXEROBJ16 hmix, LPMIXERCONTROLDETAILS16 lpmcd, DWORD fdwDetails)
816 FIXME(mmsys,"(%04x,%p,%08lx): stub!\n", hmix, lpmcd, fdwDetails);
817 return MMSYSERR_NOTENABLED;
820 /**************************************************************************
821 * mixerMessage [WINMM.109]
823 UINT WINAPI mixerMessage(HMIXER hmix, UINT uMsg, DWORD dwParam1, DWORD dwParam2)
825 LPMIXEROPENDESC lpmod;
826 UINT16 uDeviceID;
828 lpmod = (LPMIXEROPENDESC)USER_HEAP_LIN_ADDR(hmix);
829 if (lpmod)
830 uDeviceID = lpmod->uDeviceID;
831 else
832 uDeviceID = 0;
833 FIXME(mmsys,"(%04lx,%d,%08lx,%08lx): semi-stub?\n",
834 (DWORD)hmix,uMsg, dwParam1, dwParam2);
835 return mixMessage(uDeviceID,uMsg, 0L, dwParam1, dwParam2);
838 /**************************************************************************
839 * mixerMessage [MMSYSTEM.804]
841 UINT16 WINAPI mixerMessage16(HMIXER16 hmix, UINT16 uMsg, DWORD dwParam1, DWORD dwParam2)
843 LPMIXEROPENDESC lpmod;
844 UINT16 uDeviceID;
846 lpmod = (LPMIXEROPENDESC)USER_HEAP_LIN_ADDR(hmix);
847 uDeviceID = (lpmod) ? lpmod->uDeviceID : 0;
848 FIXME(mmsys,"(%04x,%d,%08lx,%08lx) - semi-stub?\n",
849 hmix,uMsg, dwParam1, dwParam2);
850 return mixMessage(uDeviceID,uMsg, 0L, dwParam1, dwParam2);
853 /**************************************************************************
854 * auxGetNumDevs [WINMM.22]
856 UINT WINAPI auxGetNumDevs()
858 return auxGetNumDevs16();
861 /**************************************************************************
862 * auxGetNumDevs [MMSYSTEM.350]
864 UINT16 WINAPI auxGetNumDevs16()
866 UINT16 count;
868 TRACE(mmsys, "\n");
869 count = auxMessage(0, AUXDM_GETNUMDEVS, 0L, 0L, 0L);
870 TRACE(mmsys, "=> %u\n", count);
871 return count;
874 /**************************************************************************
875 * auxGetDevCaps [WINMM.20]
877 UINT WINAPI auxGetDevCapsW(UINT uDeviceID, LPAUXCAPSW lpCaps, UINT uSize)
879 AUXCAPS16 ac16;
880 UINT ret = auxGetDevCaps16(uDeviceID, &ac16, sizeof(ac16));
882 lpCaps->wMid = ac16.wMid;
883 lpCaps->wPid = ac16.wPid;
884 lpCaps->vDriverVersion = ac16.vDriverVersion;
885 lstrcpyAtoW(lpCaps->szPname,ac16.szPname);
886 lpCaps->wTechnology = ac16.wTechnology;
887 lpCaps->dwSupport = ac16.dwSupport;
888 return ret;
891 /**************************************************************************
892 * auxGetDevCaps [WINMM.21]
894 UINT WINAPI auxGetDevCapsA(UINT uDeviceID, LPAUXCAPSA lpCaps, UINT uSize)
896 AUXCAPS16 ac16;
897 UINT ret = auxGetDevCaps16(uDeviceID, &ac16, sizeof(ac16));
899 lpCaps->wMid = ac16.wMid;
900 lpCaps->wPid = ac16.wPid;
901 lpCaps->vDriverVersion = ac16.vDriverVersion;
902 strcpy(lpCaps->szPname,ac16.szPname);
903 lpCaps->wTechnology = ac16.wTechnology;
904 lpCaps->dwSupport = ac16.dwSupport;
905 return ret;
908 /**************************************************************************
909 * auxGetDevCaps [MMSYSTEM.351]
911 UINT16 WINAPI auxGetDevCaps16(UINT16 uDeviceID, LPAUXCAPS16 lpCaps, UINT16 uSize)
913 TRACE(mmsys, "(%04X, %p, %d) !\n", uDeviceID, lpCaps, uSize);
915 return auxMessage(uDeviceID, AUXDM_GETDEVCAPS,
916 0L, (DWORD)lpCaps, (DWORD)uSize);
919 /**************************************************************************
920 * auxGetVolume [WINM.23]
922 UINT WINAPI auxGetVolume(UINT uDeviceID, DWORD* lpdwVolume)
924 return auxGetVolume16(uDeviceID, lpdwVolume);
927 /**************************************************************************
928 * auxGetVolume [MMSYSTEM.352]
930 UINT16 WINAPI auxGetVolume16(UINT16 uDeviceID, DWORD* lpdwVolume)
932 TRACE(mmsys, "(%04X, %p) !\n", uDeviceID, lpdwVolume);
934 return auxMessage(uDeviceID, AUXDM_GETVOLUME, 0L, (DWORD)lpdwVolume, 0L);
937 /**************************************************************************
938 * auxSetVolume [WINMM.25]
940 UINT WINAPI auxSetVolume(UINT uDeviceID, DWORD dwVolume)
942 return auxSetVolume16(uDeviceID, dwVolume);
945 /**************************************************************************
946 * auxSetVolume [MMSYSTEM.353]
948 UINT16 WINAPI auxSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
950 TRACE(mmsys, "(%04X, %08lX) !\n", uDeviceID, dwVolume);
952 return auxMessage(uDeviceID, AUXDM_SETVOLUME, 0L, dwVolume, 0L);
955 /**************************************************************************
956 * auxOutMessage [MMSYSTEM.354]
958 DWORD WINAPI auxOutMessage(UINT uDeviceID, UINT uMessage, DWORD dw1, DWORD dw2)
960 switch (uMessage) {
961 case AUXDM_GETNUMDEVS:
962 case AUXDM_GETVOLUME:
963 case AUXDM_SETVOLUME:
964 /* no argument conversion needed */
965 break;
966 case AUXDM_GETDEVCAPS:
967 return auxGetDevCapsA(uDeviceID, (LPAUXCAPSA)dw1, dw2);
968 default:
969 ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
970 uDeviceID,uMessage, dw1, dw2);
971 break;
973 return auxMessage(uDeviceID,uMessage, 0L, dw1, dw2);
976 /**************************************************************************
977 * auxOutMessage [MMSYSTEM.354]
979 DWORD WINAPI auxOutMessage16(UINT16 uDeviceID, UINT16 uMessage, DWORD dw1, DWORD dw2)
981 TRACE(mmsys, "(%04X, %04X, %08lX, %08lX)\n", uDeviceID, uMessage, dw1, dw2);
983 switch (uMessage) {
984 case AUXDM_GETNUMDEVS:
985 case AUXDM_SETVOLUME:
986 /* no argument conversion needed */
987 break;
988 case AUXDM_GETVOLUME:
989 return auxGetVolume16(uDeviceID, (LPDWORD)PTR_SEG_TO_LIN(dw1));
990 case AUXDM_GETDEVCAPS:
991 return auxGetDevCaps16(uDeviceID, (LPAUXCAPS16)PTR_SEG_TO_LIN(dw1), dw2);
992 default:
993 ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
994 uDeviceID,uMessage, dw1, dw2);
995 break;
997 return auxMessage(uDeviceID, uMessage, 0L, dw1, dw2);
1000 /**************************************************************************
1001 * mciGetErrorStringW [WINMM.46]
1003 BOOL WINAPI mciGetErrorStringW(DWORD wError, LPWSTR lpstrBuffer, UINT uLength)
1005 LPSTR bufstr = HeapAlloc(GetProcessHeap(), 0,uLength);
1006 BOOL ret = mciGetErrorStringA(wError, bufstr, uLength);
1008 lstrcpyAtoW(lpstrBuffer, bufstr);
1009 HeapFree(GetProcessHeap(), 0, bufstr);
1010 return ret;
1013 /**************************************************************************
1014 * mciGetErrorStringA [WINMM.45]
1016 BOOL WINAPI mciGetErrorStringA(DWORD wError, LPSTR lpstrBuffer, UINT uLength)
1018 return mciGetErrorString16(wError, lpstrBuffer,uLength);
1021 /**************************************************************************
1022 * mciGetErrorString [MMSYSTEM.706]
1024 BOOL16 WINAPI mciGetErrorString16(DWORD wError, LPSTR lpstrBuffer, UINT16 uLength)
1026 LPSTR msgptr;
1027 BOOL16 ret = TRUE;
1029 TRACE(mmsys, "(%08lX, %p, %d);\n", wError, lpstrBuffer, uLength);
1031 if ((lpstrBuffer == NULL) || (uLength < 1))
1032 return FALSE;
1034 lpstrBuffer[0] = '\0';
1036 switch (wError) {
1037 case 0:
1038 msgptr = "The specified command has been executed.";
1039 break;
1040 case MCIERR_INVALID_DEVICE_ID:
1041 msgptr = "Invalid MCI device ID. Use the ID returned when opening the MCI device.";
1042 break;
1043 case MCIERR_UNRECOGNIZED_KEYWORD:
1044 msgptr = "The driver cannot recognize the specified command parameter.";
1045 break;
1046 case MCIERR_UNRECOGNIZED_COMMAND:
1047 msgptr = "The driver cannot recognize the specified command.";
1048 break;
1049 case MCIERR_HARDWARE:
1050 msgptr = "There is a problem with your media device. Make sure it is working correctly or contact the device manufacturer.";
1051 break;
1052 case MCIERR_INVALID_DEVICE_NAME:
1053 msgptr = "The specified device is not open or is not recognized by MCI.";
1054 break;
1055 case MCIERR_OUT_OF_MEMORY:
1056 msgptr = "Not enough memory available for this task. \nQuit one or more applications to increase available memory, and then try again.";
1057 break;
1058 case MCIERR_DEVICE_OPEN:
1059 msgptr = "The device name is already being used as an alias by this application. Use a unique alias.";
1060 break;
1061 case MCIERR_CANNOT_LOAD_DRIVER:
1062 msgptr = "There is an undetectable problem in loading the specified device driver.";
1063 break;
1064 case MCIERR_MISSING_COMMAND_STRING:
1065 msgptr = "No command was specified.";
1066 break;
1067 case MCIERR_PARAM_OVERFLOW:
1068 msgptr = "The output string was to large to fit in the return buffer. Increase the size of the buffer.";
1069 break;
1070 case MCIERR_MISSING_STRING_ARGUMENT:
1071 msgptr = "The specified command requires a character-string parameter. Please provide one.";
1072 break;
1073 case MCIERR_BAD_INTEGER:
1074 msgptr = "The specified integer is invalid for this command.";
1075 break;
1076 case MCIERR_PARSER_INTERNAL:
1077 msgptr = "The device driver returned an invalid return type. Check with the device manufacturer about obtaining a new driver.";
1078 break;
1079 case MCIERR_DRIVER_INTERNAL:
1080 msgptr = "There is a problem with the device driver. Check with the device manufacturer about obtaining a new driver.";
1081 break;
1082 case MCIERR_MISSING_PARAMETER:
1083 msgptr = "The specified command requires a parameter. Please supply one.";
1084 break;
1085 case MCIERR_UNSUPPORTED_FUNCTION:
1086 msgptr = "The MCI device you are using does not support the specified command.";
1087 break;
1088 case MCIERR_FILE_NOT_FOUND:
1089 msgptr = "Cannot find the specified file. Make sure the path and filename are correct.";
1090 break;
1091 case MCIERR_DEVICE_NOT_READY:
1092 msgptr = "The device driver is not ready.";
1093 break;
1094 case MCIERR_INTERNAL:
1095 msgptr = "A problem occurred in initializing MCI. Try restarting Windows.";
1096 break;
1097 case MCIERR_DRIVER:
1098 msgptr = "There is a problem with the device driver. The driver has closed. Cannot access error.";
1099 break;
1100 case MCIERR_CANNOT_USE_ALL:
1101 msgptr = "Cannot use 'all' as the device name with the specified command.";
1102 break;
1103 case MCIERR_MULTIPLE:
1104 msgptr = "Errors occurred in more than one device. Specify each command and device separately to determine which devices caused the error";
1105 break;
1106 case MCIERR_EXTENSION_NOT_FOUND:
1107 msgptr = "Cannot determine the device type from the given filename extension.";
1108 break;
1109 case MCIERR_OUTOFRANGE:
1110 msgptr = "The specified parameter is out of range for the specified command.";
1111 break;
1112 case MCIERR_FLAGS_NOT_COMPATIBLE:
1113 msgptr = "The specified parameters cannot be used together.";
1114 break;
1115 case MCIERR_FILE_NOT_SAVED:
1116 msgptr = "Cannot save the specified file. Make sure you have enough disk space or are still connected to the network.";
1117 break;
1118 case MCIERR_DEVICE_TYPE_REQUIRED:
1119 msgptr = "Cannot find the specified device. Make sure it is installed or that the device name is spelled correctly.";
1120 break;
1121 case MCIERR_DEVICE_LOCKED:
1122 msgptr = "The specified device is now being closed. Wait a few seconds, and then try again.";
1123 break;
1124 case MCIERR_DUPLICATE_ALIAS:
1125 msgptr = "The specified alias is already being used in this application. Use a unique alias.";
1126 break;
1127 case MCIERR_BAD_CONSTANT:
1128 msgptr = "The specified parameter is invalid for this command.";
1129 break;
1130 case MCIERR_MUST_USE_SHAREABLE:
1131 msgptr = "The device driver is already in use. To share it, use the 'shareable' parameter with each 'open' command.";
1132 break;
1133 case MCIERR_MISSING_DEVICE_NAME:
1134 msgptr = "The specified command requires an alias, file, driver, or device name. Please supply one.";
1135 break;
1136 case MCIERR_BAD_TIME_FORMAT:
1137 msgptr = "The specified value for the time format is invalid. Refer to the MCI documentation for valid formats.";
1138 break;
1139 case MCIERR_NO_CLOSING_QUOTE:
1140 msgptr = "A closing double-quotation mark is missing from the parameter value. Please supply one.";
1141 break;
1142 case MCIERR_DUPLICATE_FLAGS:
1143 msgptr = "A parameter or value was specified twice. Only specify it once.";
1144 break;
1145 case MCIERR_INVALID_FILE:
1146 msgptr = "The specified file cannot be played on the specified MCI device. The file may be corrupt, or not in the correct format.";
1147 break;
1148 case MCIERR_NULL_PARAMETER_BLOCK:
1149 msgptr = "A null parameter block was passed to MCI.";
1150 break;
1151 case MCIERR_UNNAMED_RESOURCE:
1152 msgptr = "Cannot save an unnamed file. Supply a filename.";
1153 break;
1154 case MCIERR_NEW_REQUIRES_ALIAS:
1155 msgptr = "You must specify an alias when using the 'new' parameter.";
1156 break;
1157 case MCIERR_NOTIFY_ON_AUTO_OPEN:
1158 msgptr = "Cannot use the 'notify' flag with auto-opened devices.";
1159 break;
1160 case MCIERR_NO_ELEMENT_ALLOWED:
1161 msgptr = "Cannot use a filename with the specified device.";
1162 break;
1163 case MCIERR_NONAPPLICABLE_FUNCTION:
1164 msgptr = "Cannot carry out the commands in the order specified. Correct the command sequence, and then try again.";
1165 break;
1166 case MCIERR_ILLEGAL_FOR_AUTO_OPEN:
1167 msgptr = "Cannot carry out the specified command on an auto-opened device. Wait until the device is closed, and then try again.";
1168 break;
1169 case MCIERR_FILENAME_REQUIRED:
1170 msgptr = "The filename is invalid. Make sure the filename is not longer than 8 characters, followed by a period and an extension.";
1171 break;
1172 case MCIERR_EXTRA_CHARACTERS:
1173 msgptr = "Cannot specify extra characters after a string enclosed in quotation marks.";
1174 break;
1175 case MCIERR_DEVICE_NOT_INSTALLED:
1176 msgptr = "The specified device is not installed on the system. Use the Drivers option in Control Panel to install the device.";
1177 break;
1178 case MCIERR_GET_CD:
1179 msgptr = "Cannot access the specified file or MCI device. Try changing directories or restarting your computer.";
1180 break;
1181 case MCIERR_SET_CD:
1182 msgptr = "Cannot access the specified file or MCI device because the application cannot change directories.";
1183 break;
1184 case MCIERR_SET_DRIVE:
1185 msgptr = "Cannot access specified file or MCI device because the application cannot change drives.";
1186 break;
1187 case MCIERR_DEVICE_LENGTH:
1188 msgptr = "Specify a device or driver name that is less than 79 characters.";
1189 break;
1190 case MCIERR_DEVICE_ORD_LENGTH:
1191 msgptr = "Specify a device or driver name that is less than 69 characters.";
1192 break;
1193 case MCIERR_NO_INTEGER:
1194 msgptr = "The specified command requires an integer parameter. Please provide one.";
1195 break;
1196 case MCIERR_WAVE_OUTPUTSINUSE:
1197 msgptr = "All wave devices that can play files in the current format are in use. Wait until a wave device is free, and then try again.";
1198 break;
1199 case MCIERR_WAVE_SETOUTPUTINUSE:
1200 msgptr = "Cannot set the current wave device for play back because it is in use. Wait until the device is free, and then try again.";
1201 break;
1202 case MCIERR_WAVE_INPUTSINUSE:
1203 msgptr = "All wave devices that can record files in the current format are in use. Wait until a wave device is free, and then try again.";
1204 break;
1205 case MCIERR_WAVE_SETINPUTINUSE:
1206 msgptr = "Cannot set the current wave device for recording because it is in use. Wait until the device is free, and then try again.";
1207 break;
1208 case MCIERR_WAVE_OUTPUTUNSPECIFIED:
1209 msgptr = "Any compatible waveform playback device may be used.";
1210 break;
1211 case MCIERR_WAVE_INPUTUNSPECIFIED:
1212 msgptr = "Any compatible waveform recording device may be used.";
1213 break;
1214 case MCIERR_WAVE_OUTPUTSUNSUITABLE:
1215 msgptr = "No wave device that can play files in the current format is installed. Use the Drivers option to install the wave device.";
1216 break;
1217 case MCIERR_WAVE_SETOUTPUTUNSUITABLE:
1218 msgptr = "The device you are trying to play to cannot recognize the current file format.";
1219 break;
1220 case MCIERR_WAVE_INPUTSUNSUITABLE:
1221 msgptr = "No wave device that can record files in the current format is installed. Use the Drivers option to install the wave device.";
1222 break;
1223 case MCIERR_WAVE_SETINPUTUNSUITABLE:
1224 msgptr = "The device you are trying to record from cannot recognize the current file format.";
1225 break;
1226 case MCIERR_NO_WINDOW:
1227 msgptr = "There is no display window.";
1228 break;
1229 case MCIERR_CREATEWINDOW:
1230 msgptr = "Could not create or use window.";
1231 break;
1232 case MCIERR_FILE_READ:
1233 msgptr = "Cannot read the specified file. Make sure the file is still present, or check your disk or network connection.";
1234 break;
1235 case MCIERR_FILE_WRITE:
1236 msgptr = "Cannot write to the specified file. Make sure you have enough disk space or are still connected to the network.";
1237 break;
1238 case MCIERR_SEQ_DIV_INCOMPATIBLE:
1239 msgptr = "The time formats of the \"song pointer\" and SMPTE are mutually exclusive. You can't use them together.";
1240 break;
1241 case MCIERR_SEQ_NOMIDIPRESENT:
1242 msgptr = "The system has no installed MIDI devices. Use the Drivers option from the Control Panel to install a MIDI driver.";
1243 break;
1244 case MCIERR_SEQ_PORT_INUSE:
1245 msgptr = "The specified MIDI port is already in use. Wait until it is free; the try again.";
1246 break;
1247 case MCIERR_SEQ_PORT_MAPNODEVICE:
1248 msgptr = "The current MIDI Mapper setup refers to a MIDI device that is not installed on the system. Use the MIDI Mapper option from the Control Panel to edit the setup.";
1249 break;
1250 case MCIERR_SEQ_PORT_MISCERROR:
1251 msgptr = "An error occurred with the specified port.";
1252 break;
1253 case MCIERR_SEQ_PORT_NONEXISTENT:
1254 msgptr = "The specified MIDI device is not installed on the system. Use the Drivers option from the Control Panel to install a MIDI device.";
1255 break;
1256 case MCIERR_SEQ_PORTUNSPECIFIED:
1257 msgptr = "The system doesnot have a current MIDI port specified.";
1258 break;
1259 case MCIERR_SEQ_TIMER:
1260 msgptr = "All multimedia timers are being used by other applications. Quit one of these applications; then, try again.";
1261 break;
1264 msg# 513 : vcr
1265 msg# 514 : videodisc
1266 msg# 515 : overlay
1267 msg# 516 : cdaudio
1268 msg# 517 : dat
1269 msg# 518 : scanner
1270 msg# 519 : animation
1271 msg# 520 : digitalvideo
1272 msg# 521 : other
1273 msg# 522 : waveaudio
1274 msg# 523 : sequencer
1275 msg# 524 : not ready
1276 msg# 525 : stopped
1277 msg# 526 : playing
1278 msg# 527 : recording
1279 msg# 528 : seeking
1280 msg# 529 : paused
1281 msg# 530 : open
1282 msg# 531 : false
1283 msg# 532 : true
1284 msg# 533 : milliseconds
1285 msg# 534 : hms
1286 msg# 535 : msf
1287 msg# 536 : frames
1288 msg# 537 : smpte 24
1289 msg# 538 : smpte 25
1290 msg# 539 : smpte 30
1291 msg# 540 : smpte 30 drop
1292 msg# 541 : bytes
1293 msg# 542 : samples
1294 msg# 543 : tmsf
1296 default:
1297 msgptr = "Unknown MCI Error !\n";
1298 ret = FALSE;
1299 break;
1301 lstrcpynA(lpstrBuffer, msgptr, uLength);
1302 TRACE(mmsys, "msg = %s;\n", msgptr);
1303 return ret;
1306 /**************************************************************************
1307 * mciDriverNotify [MMSYSTEM.711]
1309 BOOL16 WINAPI mciDriverNotify16(HWND16 hWndCallBack, UINT16 wDevID, UINT16 wStatus)
1311 TRACE(mmsys, "(%04X, %04x, %04X)\n", hWndCallBack, wDevID, wStatus);
1313 if (!IsWindow(hWndCallBack)) {
1314 WARN(mmsys, "bad hWnd for call back\n");
1315 return FALSE;
1317 TRACE(mmsys, "before PostMessage\n");
1318 PostMessageA(hWndCallBack, MM_MCINOTIFY, wStatus, wDevID);
1319 return TRUE;
1322 /**************************************************************************
1323 * mciDriverNotify [WINMM.36]
1325 BOOL WINAPI mciDriverNotify(HWND hWndCallBack, UINT wDevID, UINT wStatus)
1327 FIXME(mmsys, "(%08X, %04x, %04X)\n", hWndCallBack, wDevID, wStatus);
1329 if (!IsWindow(hWndCallBack)) {
1330 WARN(mmsys, "bad hWnd for call back\n");
1331 return FALSE;
1333 TRACE(mmsys, "before PostMessage\n");
1334 PostMessageA(hWndCallBack, MM_MCINOTIFY, wStatus, wDevID);
1335 return TRUE;
1338 /**************************************************************************
1339 * mciGetDriverData [MMSYSTEM.708]
1341 DWORD WINAPI mciGetDriverData16(UINT16 uDeviceID)
1343 return mciGetDriverData(uDeviceID);
1346 /**************************************************************************
1347 * mciGetDriverData [WINMM.44]
1349 DWORD WINAPI mciGetDriverData(UINT uDeviceID)
1351 TRACE(mmsys,"(%04x)\n", uDeviceID);
1352 if (!MCI_DevIDValid(uDeviceID) || MCI_GetDrv(uDeviceID)->modp.wType == 0) {
1353 WARN(mmsys, "Bad uDeviceID\n");
1354 return 0L;
1357 return MCI_GetDrv(uDeviceID)->dwPrivate;
1360 /**************************************************************************
1361 * mciSetDriverData [MMSYSTEM.707]
1363 BOOL16 WINAPI mciSetDriverData16(UINT16 uDeviceID, DWORD data)
1365 return mciSetDriverData(uDeviceID, data);
1368 /**************************************************************************
1369 * mciSetDriverData [WINMM.53]
1371 BOOL WINAPI mciSetDriverData(UINT uDeviceID, DWORD data)
1373 TRACE(mmsys, "(%04x,%08lx)\n", uDeviceID, data);
1374 if (!MCI_DevIDValid(uDeviceID) || MCI_GetDrv(uDeviceID)->modp.wType == 0) {
1375 WARN(mmsys, "Bad uDeviceID\n");
1376 return FALSE;
1379 MCI_GetDrv(uDeviceID)->dwPrivate = data;
1380 return TRUE;
1383 /**************************************************************************
1384 * mciLoadCommandResource [MMSYSTEM.705]
1386 UINT16 WINAPI mciLoadCommandResource16(HANDLE16 hinst, LPCSTR resname, UINT16 type)
1388 char buf[200];
1389 OFSTRUCT ofs;
1390 HANDLE16 xhinst;
1391 HRSRC16 hrsrc;
1392 HGLOBAL16 hmem;
1393 LPSTR segstr;
1394 SEGPTR xmem;
1395 LPBYTE lmem;
1396 static UINT16 mcidevtype = 0;
1398 FIXME(mmsys,"(%04x,%s,%d): stub!\n", hinst, resname, type);
1399 if (!lstrcmpiA(resname, "core")) {
1400 FIXME(mmsys, "(...,\"core\",...), have to use internal tables... (not there yet)\n");
1401 return 0;
1403 return ++mcidevtype;
1404 /* if file exists "resname.mci", then load resource "resname" from it
1405 * otherwise directly from driver
1407 strcpy(buf,resname);
1408 strcat(buf,".mci");
1409 if (OpenFile(buf, &ofs,OF_EXIST) != HFILE_ERROR) {
1410 xhinst = LoadLibrary16(buf);
1411 if (xhinst > 32)
1412 hinst = xhinst;
1413 } /* else use passed hinst */
1414 segstr = SEGPTR_STRDUP(resname);
1415 hrsrc = FindResource16(hinst, SEGPTR_GET(segstr), type);
1416 SEGPTR_FREE(segstr);
1417 if (!hrsrc) {
1418 WARN(mmsys, "no special commandlist found in resource\n");
1419 return MCI_NO_COMMAND_TABLE;
1421 hmem = LoadResource16(hinst, hrsrc);
1422 if (!hmem) {
1423 WARN(mmsys, "couldn't load resource??\n");
1424 return MCI_NO_COMMAND_TABLE;
1426 xmem = WIN16_LockResource16(hmem);
1427 if (!xmem) {
1428 WARN(mmsys, "couldn't lock resource??\n");
1429 FreeResource16(hmem);
1430 return MCI_NO_COMMAND_TABLE;
1432 lmem = PTR_SEG_TO_LIN(xmem);
1433 TRACE(mmsys, "first resource entry is %s\n", (char*)lmem);
1434 /* parse resource, register stuff, return unique id */
1435 return ++mcidevtype;
1438 /**************************************************************************
1439 * mciFreeCommandResource [MMSYSTEM.713]
1441 BOOL16 WINAPI mciFreeCommandResource16(UINT16 uTable)
1443 FIXME(mci, "(%04x) stub\n", uTable);
1444 return 0;
1447 /**************************************************************************
1448 * mciFreeCommandResource [WINMM.39]
1450 BOOL WINAPI mciFreeCommandResource(UINT uTable)
1452 FIXME(mci, "(%08x) stub\n", uTable);
1453 return 0;
1456 /**************************************************************************
1457 * mciLoadCommandResource [WINMM.48]
1459 UINT WINAPI mciLoadCommandResource(HANDLE hinst, LPCWSTR resname, UINT type)
1461 FIXME(mci, "(%04x,%s,%d): stub!\n", hinst, debugstr_w(resname), type);
1462 return 0;
1465 /**************************************************************************
1466 * mciSendCommandA [WINMM.49]
1468 DWORD WINAPI mciSendCommandA(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2)
1470 DWORD dwRet;
1472 TRACE(mci, "(%08x,%s,%08lx,%08lx)\n", wDevID, MCI_CommandToString(wMsg), dwParam1, dwParam2);
1474 switch (wMsg) {
1475 case MCI_OPEN:
1476 dwRet = MCI_Open(dwParam1, (LPMCI_OPEN_PARMSA)dwParam2);
1477 break;
1478 case MCI_CLOSE:
1479 dwRet = MCI_Close(wDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
1480 break;
1481 case MCI_SYSINFO:
1482 dwRet = MCI_SysInfo(wDevID, dwParam1, (LPMCI_SYSINFO_PARMSA)dwParam2);
1483 break;
1484 default:
1485 if (wDevID == MCI_ALL_DEVICE_ID) {
1486 FIXME(mci, "unhandled MCI_ALL_DEVICE_ID\n");
1487 dwRet = MCIERR_CANNOT_USE_ALL;
1488 } else {
1489 dwRet = MCI_SendCommand(wDevID, wMsg, dwParam1, dwParam2);
1491 break;
1493 dwRet = MCI_CleanUp(dwRet, wMsg, dwParam2, TRUE);
1494 TRACE(mci, "=> %08ld\n", dwRet);
1495 return dwRet;
1498 /**************************************************************************
1499 * mciSendCommandW [WINMM.50]
1501 DWORD WINAPI mciSendCommandW(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2)
1503 return 0x1; /* !ok */
1506 /**************************************************************************
1507 * mciSendCommand [MMSYSTEM.701]
1509 DWORD WINAPI mciSendCommand16(UINT16 wDevID, UINT16 wMsg, DWORD dwParam1, DWORD dwParam2)
1511 DWORD dwRet = MCIERR_UNRECOGNIZED_COMMAND;
1513 TRACE(mmsys, "(%04X, %s, %08lX, %08lX)\n",
1514 wDevID, MCI_CommandToString(wMsg), dwParam1, dwParam2);
1516 switch (wMsg) {
1517 case MCI_OPEN:
1518 if (MCI_MapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, &dwParam2) >= 0) {
1519 dwRet = MCI_Open(dwParam1, (LPMCI_OPEN_PARMSA)dwParam2);
1520 MCI_UnMapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam2);
1522 break;
1523 case MCI_CLOSE:
1524 if (wDevID == MCI_ALL_DEVICE_ID) {
1525 FIXME(mci, "unhandled MCI_ALL_DEVICE_ID\n");
1526 dwRet = MCIERR_CANNOT_USE_ALL;
1527 } else if (!MCI_DevIDValid(wDevID)) {
1528 dwRet = MCIERR_INVALID_DEVICE_ID;
1529 } else if (MCI_MapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, &dwParam2) >= 0) {
1530 dwRet = MCI_Close(wDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
1531 MCI_UnMapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam2);
1533 break;
1534 case MCI_SYSINFO:
1535 if (MCI_MapMsg16To32A(0, wDevID, &dwParam2) >= 0) {
1536 dwRet = MCI_SysInfo(wDevID, dwParam1, (LPMCI_SYSINFO_PARMSA)dwParam2);
1537 MCI_UnMapMsg16To32A(0, wDevID, dwParam2);
1539 break;
1540 /* FIXME: it seems that MCI_BREAK and MCI_SOUND need the same handling */
1541 default:
1542 if (wDevID == MCI_ALL_DEVICE_ID) {
1543 FIXME(mci, "unhandled MCI_ALL_DEVICE_ID\n");
1544 dwRet = MCIERR_CANNOT_USE_ALL;
1545 } else if (!MCI_DevIDValid(wDevID)) {
1546 dwRet = MCIERR_INVALID_DEVICE_ID;
1547 } else {
1548 int res;
1550 switch (DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv)) {
1551 case WINE_DI_TYPE_16:
1552 dwRet = SendDriverMessage16(MCI_GetDrv(wDevID)->hDrv, wMsg, dwParam1, dwParam2);
1553 break;
1554 case WINE_DI_TYPE_32:
1555 switch (res = MCI_MapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, &dwParam2)) {
1556 case -1:
1557 TRACE(mci, "Not handled yet (%s)\n", MCI_CommandToString(wMsg));
1558 dwRet = MCIERR_DRIVER_INTERNAL;
1559 break;
1560 case -2:
1561 TRACE(mci, "Problem mapping msg=%s from 16 to 32a\n", MCI_CommandToString(wMsg));
1562 dwRet = MCIERR_OUT_OF_MEMORY;
1563 break;
1564 case 0:
1565 case 1:
1566 dwRet = MCI_SendCommand(wDevID, wMsg, dwParam1, dwParam2);
1567 if (res)
1568 MCI_UnMapMsg16To32A(MCI_GetDrv(wDevID)->modp.wType, wMsg, dwParam2);
1569 break;
1571 break;
1572 default:
1573 WARN(mmsys, "Unknown driver type=%u\n", DRIVER_GetType(MCI_GetDrv(wDevID)->hDrv));
1574 dwRet = MCIERR_DRIVER_INTERNAL;
1578 dwRet = MCI_CleanUp(dwRet, wMsg, dwParam2, FALSE);
1579 TRACE(mmsys, "=> %ld\n", dwRet);
1580 return dwRet;
1583 /**************************************************************************
1584 * mciGetDeviceID [MMSYSTEM.703]
1586 UINT16 WINAPI mciGetDeviceID16(LPCSTR lpstrName)
1588 UINT16 wDevID;
1589 TRACE(mmsys, "(\"%s\")\n", lpstrName);
1591 if (!lpstrName)
1592 return 0;
1594 if (!lstrcmpiA(lpstrName, "ALL"))
1595 return MCI_ALL_DEVICE_ID;
1597 for (wDevID = MCI_FirstDevID(); MCI_DevIDValid(wDevID); wDevID = MCI_NextDevID(wDevID)) {
1598 if (MCI_GetDrv(wDevID)->modp.wType) {
1599 FIXME(mmsys, "This is wrong for compound devices\n");
1600 /* FIXME: for compound devices, lpstrName is matched against
1601 * the name of the file, not the name of the device...
1603 if (MCI_GetOpenDrv(wDevID)->lpstrDeviceType &&
1604 strcmp(MCI_GetOpenDrv(wDevID)->lpstrDeviceType, lpstrName) == 0)
1605 return wDevID;
1607 if (MCI_GetOpenDrv(wDevID)->lpstrAlias &&
1608 strcmp(MCI_GetOpenDrv(wDevID)->lpstrAlias, lpstrName) == 0)
1609 return wDevID;
1613 return 0;
1616 /**************************************************************************
1617 * mciGetDeviceIDA [WINMM.41]
1619 UINT WINAPI mciGetDeviceIDA(LPCSTR lpstrName)
1621 return mciGetDeviceID16(lpstrName);
1624 /**************************************************************************
1625 * mciGetDeviceIDW [WINMM.43]
1627 UINT WINAPI mciGetDeviceIDW(LPCWSTR lpwstrName)
1629 LPSTR lpstrName;
1630 UINT ret;
1632 lpstrName = HEAP_strdupWtoA(GetProcessHeap(), 0, lpwstrName);
1633 ret = mciGetDeviceID16(lpstrName);
1634 HeapFree(GetProcessHeap(), 0, lpstrName);
1635 return ret;
1638 /**************************************************************************
1639 * mciSetYieldProc [MMSYSTEM.714]
1641 BOOL16 WINAPI mciSetYieldProc16(UINT16 uDeviceID, YIELDPROC fpYieldProc, DWORD dwYieldData)
1643 TRACE(mmsys, "(%u, %p, %08lx)\n", uDeviceID, fpYieldProc, dwYieldData);
1644 if (!MCI_DevIDValid(uDeviceID) || MCI_GetDrv(uDeviceID)->modp.wType == 0) {
1645 WARN(mmsys, "Bad uDeviceID\n");
1646 return FALSE;
1649 MCI_GetDrv(uDeviceID)->lpfnYieldProc = fpYieldProc;
1650 MCI_GetDrv(uDeviceID)->dwYieldData = dwYieldData;
1651 MCI_GetDrv(uDeviceID)->bIs32 = FALSE;
1653 return TRUE;
1656 /**************************************************************************
1657 * mciSetYieldProc [WINMM.54]
1659 BOOL WINAPI mciSetYieldProc(UINT uDeviceID, YIELDPROC fpYieldProc, DWORD dwYieldData)
1661 TRACE(mmsys, "(%u, %p, %08lx)\n", uDeviceID, fpYieldProc, dwYieldData);
1662 if (!MCI_DevIDValid(uDeviceID) || MCI_GetDrv(uDeviceID)->modp.wType == 0) {
1663 WARN(mmsys, "Bad uDeviceID\n");
1664 return FALSE;
1667 MCI_GetDrv(uDeviceID)->lpfnYieldProc = fpYieldProc;
1668 MCI_GetDrv(uDeviceID)->dwYieldData = dwYieldData;
1669 MCI_GetDrv(uDeviceID)->bIs32 = TRUE;
1671 return TRUE;
1674 /**************************************************************************
1675 * mciGetDeviceIDFromElementID [MMSYSTEM.715]
1677 UINT16 WINAPI mciGetDeviceIDFromElementID16(DWORD dwElementID, LPCSTR lpstrType)
1679 FIXME(mci, "(%lu, %s) stub\n", dwElementID, lpstrType);
1680 return 0;
1683 /**************************************************************************
1684 * mciGetDeviceIDFromElementIDW [WINMM.42]
1686 UINT WINAPI mciGetDeviceIDFromElementIDW(DWORD dwElementID, LPCWSTR lpstrType)
1688 /* FIXME: that's rather strange, there is no
1689 * mciGetDeviceIDFromElementID32A in winmm.spec
1691 FIXME(mci, "(%lu, %p) stub\n", dwElementID, lpstrType);
1692 return 0;
1695 /**************************************************************************
1696 * mciGetYieldProc [MMSYSTEM.716]
1698 YIELDPROC WINAPI mciGetYieldProc16(UINT16 uDeviceID, DWORD* lpdwYieldData)
1700 TRACE(mmsys, "(%u, %p)\n", uDeviceID, lpdwYieldData);
1701 if (!MCI_DevIDValid(uDeviceID) || MCI_GetDrv(uDeviceID)->modp.wType == 0) {
1702 WARN(mmsys, "Bad uDeviceID\n");
1703 return NULL;
1705 if (!MCI_GetDrv(uDeviceID)->lpfnYieldProc) {
1706 WARN(mmsys, "No proc set\n");
1707 return NULL;
1709 if (MCI_GetDrv(uDeviceID)->bIs32) {
1710 WARN(mmsys, "Proc is 32 bit\n");
1711 return NULL;
1713 return MCI_GetDrv(uDeviceID)->lpfnYieldProc;
1716 /**************************************************************************
1717 * mciGetYieldProc [WINMM.47]
1719 YIELDPROC WINAPI mciGetYieldProc(UINT uDeviceID, DWORD* lpdwYieldData)
1721 TRACE(mmsys, "(%u, %p)\n", uDeviceID, lpdwYieldData);
1722 if (!MCI_DevIDValid(uDeviceID) || MCI_GetDrv(uDeviceID)->modp.wType == 0) {
1723 WARN(mmsys, "Bad uDeviceID\n");
1724 return NULL;
1726 if (!MCI_GetDrv(uDeviceID)->lpfnYieldProc) {
1727 WARN(mmsys, "No proc set\n");
1728 return NULL;
1730 if (!MCI_GetDrv(uDeviceID)->bIs32) {
1731 WARN(mmsys, "Proc is 32 bit\n");
1732 return NULL;
1734 return MCI_GetDrv(uDeviceID)->lpfnYieldProc;
1737 /**************************************************************************
1738 * mciGetCreatorTask [MMSYSTEM.717]
1740 HTASK16 WINAPI mciGetCreatorTask16(UINT16 uDeviceID)
1742 FIXME(mci, "(%u) stub\n", uDeviceID);
1743 return 0;
1746 /**************************************************************************
1747 * mciGetCreatorTask [WINMM.40]
1749 HTASK WINAPI mciGetCreatorTask(UINT uDeviceID)
1751 FIXME(mci, "(%u) stub\n", uDeviceID);
1752 return 0;
1755 /**************************************************************************
1756 * mciDriverYield [MMSYSTEM.710]
1758 UINT16 WINAPI mciDriverYield16(UINT16 uDeviceID)
1760 UINT16 ret = 0;
1762 TRACE(mmsys,"(%04x)\n", uDeviceID);
1763 if (!MCI_DevIDValid(uDeviceID) || MCI_GetDrv(uDeviceID)->modp.wType == 0 ||
1764 !MCI_GetDrv(uDeviceID)->lpfnYieldProc || MCI_GetDrv(uDeviceID)->bIs32) {
1765 OldYield16();
1766 } else {
1767 ret = MCI_GetDrv(uDeviceID)->lpfnYieldProc(uDeviceID, MCI_GetDrv(uDeviceID)->dwYieldData);
1770 return ret;
1773 /**************************************************************************
1774 * mciDriverYield [WINMM.37]
1776 UINT WINAPI mciDriverYield(UINT uDeviceID)
1778 UINT ret = 0;
1780 TRACE(mmsys,"(%04x)\n", uDeviceID);
1781 if (!MCI_DevIDValid(uDeviceID) || MCI_GetDrv(uDeviceID)->modp.wType == 0 ||
1782 !MCI_GetDrv(uDeviceID)->lpfnYieldProc || !MCI_GetDrv(uDeviceID)->bIs32) {
1783 OldYield16();
1784 } else {
1785 ret = MCI_GetDrv(uDeviceID)->lpfnYieldProc(uDeviceID, MCI_GetDrv(uDeviceID)->dwYieldData);
1788 return ret;
1791 /**************************************************************************
1792 * midiOutGetNumDevs [WINMM.80]
1794 UINT WINAPI midiOutGetNumDevs(void)
1796 return midiOutGetNumDevs16();
1799 /**************************************************************************
1800 * midiOutGetNumDevs [MMSYSTEM.201]
1802 UINT16 WINAPI midiOutGetNumDevs16(void)
1804 UINT16 count = modMessage(0, MODM_GETNUMDEVS, 0L, 0L, 0L);
1806 TRACE(mmsys, "returns %u\n", count);
1807 return count;
1810 /**************************************************************************
1811 * midiOutGetDevCapsW [WINMM.76]
1813 UINT WINAPI midiOutGetDevCapsW(UINT uDeviceID, LPMIDIOUTCAPSW lpCaps, UINT uSize)
1815 MIDIOUTCAPS16 moc16;
1816 UINT ret;
1818 ret = midiOutGetDevCaps16(uDeviceID, &moc16, sizeof(moc16));
1819 lpCaps->wMid = moc16.wMid;
1820 lpCaps->wPid = moc16.wPid;
1821 lpCaps->vDriverVersion = moc16.vDriverVersion;
1822 lstrcpyAtoW(lpCaps->szPname, moc16.szPname);
1823 lpCaps->wTechnology = moc16.wTechnology;
1824 lpCaps->wVoices = moc16.wVoices;
1825 lpCaps->wNotes = moc16.wNotes;
1826 lpCaps->wChannelMask = moc16.wChannelMask;
1827 lpCaps->dwSupport = moc16.dwSupport;
1828 return ret;
1831 /**************************************************************************
1832 * midiOutGetDevCapsA [WINMM.75]
1834 UINT WINAPI midiOutGetDevCapsA(UINT uDeviceID, LPMIDIOUTCAPSA lpCaps, UINT uSize)
1836 MIDIOUTCAPS16 moc16;
1837 UINT ret;
1839 ret = midiOutGetDevCaps16(uDeviceID, &moc16, sizeof(moc16));
1840 lpCaps->wMid = moc16.wMid;
1841 lpCaps->wPid = moc16.wPid;
1842 lpCaps->vDriverVersion = moc16.vDriverVersion;
1843 strcpy(lpCaps->szPname, moc16.szPname);
1844 lpCaps->wTechnology = moc16.wTechnology;
1845 lpCaps->wVoices = moc16.wVoices;
1846 lpCaps->wNotes = moc16.wNotes;
1847 lpCaps->wChannelMask = moc16.wChannelMask;
1848 lpCaps->dwSupport = moc16.dwSupport;
1849 return ret;
1852 /**************************************************************************
1853 * midiOutGetDevCaps [MMSYSTEM.202]
1855 UINT16 WINAPI midiOutGetDevCaps16(UINT16 uDeviceID, LPMIDIOUTCAPS16 lpCaps, UINT16 uSize)
1857 TRACE(mmsys, "midiOutGetDevCaps\n");
1858 return modMessage(uDeviceID, MODM_GETDEVCAPS, 0, (DWORD)lpCaps,uSize);
1861 /**************************************************************************
1862 * midiOutGetErrorTextA [WINMM.77]
1864 UINT WINAPI midiOutGetErrorTextA(UINT uError, LPSTR lpText, UINT uSize)
1866 TRACE(mmsys, "midiOutGetErrorText\n");
1867 return midiGetErrorText(uError, lpText, uSize);
1870 /**************************************************************************
1871 * midiOutGetErrorTextW [WINMM.78]
1873 UINT WINAPI midiOutGetErrorTextW(UINT uError, LPWSTR lpText, UINT uSize)
1875 LPSTR xstr = HeapAlloc(GetProcessHeap(), 0,uSize);
1876 UINT ret;
1878 TRACE(mmsys, "midiOutGetErrorText\n");
1879 ret = midiGetErrorText(uError, xstr, uSize);
1880 lstrcpyAtoW(lpText,xstr);
1881 HeapFree(GetProcessHeap(), 0,xstr);
1882 return ret;
1885 /**************************************************************************
1886 * midiOutGetErrorText [MMSYSTEM.203]
1888 UINT16 WINAPI midiOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
1890 TRACE(mmsys, "midiOutGetErrorText\n");
1891 return midiGetErrorText(uError, lpText, uSize);
1894 /**************************************************************************
1895 * midiGetErrorText [internal]
1897 UINT16 WINAPI midiGetErrorText(UINT16 uError, LPSTR lpText, UINT16 uSize)
1899 LPSTR msgptr;
1900 if ((lpText == NULL) || (uSize < 1)) return(FALSE);
1901 lpText[0] = '\0';
1902 switch (uError) {
1903 case MIDIERR_UNPREPARED:
1904 msgptr = "The MIDI header was not prepared. Use the Prepare function to prepare the header, and then try again.";
1905 break;
1906 case MIDIERR_STILLPLAYING:
1907 msgptr = "Cannot perform this operation while media data is still playing. Reset the device, or wait until the data is finished playing.";
1908 break;
1909 case MIDIERR_NOMAP:
1910 msgptr = "A MIDI map was not found. There may be a problem with the driver, or the MIDIMAP.CFG file may be corrupt or missing.";
1911 break;
1912 case MIDIERR_NOTREADY:
1913 msgptr = "The port is transmitting data to the device. Wait until the data has been transmitted, and then try again.";
1914 break;
1915 case MIDIERR_NODEVICE:
1916 msgptr = "The current MIDI Mapper setup refers to a MIDI device that is not installed on the system. Use MIDI Mapper to edit the setup.";
1917 break;
1918 case MIDIERR_INVALIDSETUP:
1919 msgptr = "The current MIDI setup is damaged. Copy the original MIDIMAP.CFG file to the Windows SYSTEM directory, and then try again.";
1920 break;
1922 msg# 336 : Cannot use the song-pointer time format and the SMPTE time-format together.
1923 msg# 337 : The specified MIDI device is already in use. Wait until it is free, and then try again.
1924 msg# 338 : The specified MIDI device is not installed on the system. Use the Drivers option in Control Panel to install the driver.
1925 msg# 339 : The current MIDI Mapper setup refers to a MIDI device that is not installed on the system. Use MIDI Mapper to edit the setup.
1926 msg# 340 : An error occurred using the specified port.
1927 msg# 341 : All multimedia timers are being used by other applications. Quit one of these applications, and then try again.
1928 msg# 342 : There is no current MIDI port.
1929 msg# 343 : There are no MIDI devices installed on the system. Use the Drivers option in Control Panel to install the driver.
1931 default:
1932 msgptr = "Unknown MIDI Error !\n";
1933 break;
1935 lstrcpynA(lpText, msgptr, uSize);
1936 return TRUE;
1939 /**************************************************************************
1940 * midiOutOpen [WINM.84]
1942 UINT WINAPI midiOutOpen(HMIDIOUT* lphMidiOut, UINT uDeviceID,
1943 DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
1945 HMIDIOUT16 hmo16;
1946 UINT ret;
1948 ret = midiOutOpen16(&hmo16,uDeviceID, dwCallback, dwInstance,
1949 CALLBACK32CONV(dwFlags));
1950 if (lphMidiOut) *lphMidiOut = hmo16;
1951 return ret;
1954 /**************************************************************************
1955 * midiOutOpen [MMSYSTEM.204]
1957 UINT16 WINAPI midiOutOpen16(HMIDIOUT16* lphMidiOut, UINT16 uDeviceID,
1958 DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
1960 HMIDI16 hMidiOut;
1961 LPMIDIOPENDESC lpDesc;
1962 DWORD dwRet = 0;
1963 BOOL bMapperFlg = FALSE;
1965 if (lphMidiOut != NULL) *lphMidiOut = 0;
1966 TRACE(mmsys, "(%p, %d, %08lX, %08lX, %08lX);\n",
1967 lphMidiOut, uDeviceID, dwCallback, dwInstance, dwFlags);
1968 if (uDeviceID == (UINT16)MIDI_MAPPER) {
1969 TRACE(mmsys, "MIDI_MAPPER mode requested !\n");
1970 bMapperFlg = TRUE;
1971 uDeviceID = 0;
1973 hMidiOut = USER_HEAP_ALLOC(sizeof(MIDIOPENDESC));
1974 if (lphMidiOut != NULL)
1975 *lphMidiOut = hMidiOut;
1976 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
1977 if (lpDesc == NULL)
1978 return MMSYSERR_NOMEM;
1979 lpDesc->hMidi = hMidiOut;
1980 lpDesc->dwCallback = dwCallback;
1981 lpDesc->dwInstance = dwInstance;
1983 while (uDeviceID < MAXMIDIDRIVERS) {
1984 dwRet = modMessage(uDeviceID, MODM_OPEN,
1985 lpDesc->dwInstance, (DWORD)lpDesc, dwFlags);
1986 if (dwRet == MMSYSERR_NOERROR) break;
1987 if (!bMapperFlg) break;
1988 uDeviceID++;
1989 TRACE(mmsys, "MIDI_MAPPER mode ! try next driver...\n");
1991 lpDesc->wDevID = uDeviceID;
1992 return dwRet;
1995 /**************************************************************************
1996 * midiOutClose [WINMM.74]
1998 UINT WINAPI midiOutClose(HMIDIOUT hMidiOut)
2000 return midiOutClose16(hMidiOut);
2003 /**************************************************************************
2004 * midiOutClose [MMSYSTEM.205]
2006 UINT16 WINAPI midiOutClose16(HMIDIOUT16 hMidiOut)
2008 LPMIDIOPENDESC lpDesc;
2010 TRACE(mmsys, "(%04X)\n", hMidiOut);
2012 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2013 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2014 return modMessage(lpDesc->wDevID, MODM_CLOSE, lpDesc->dwInstance, 0L, 0L);
2017 /**************************************************************************
2018 * midiOutPrepareHeader [WINMM.85]
2020 UINT WINAPI midiOutPrepareHeader(HMIDIOUT hMidiOut,
2021 MIDIHDR16* lpMidiOutHdr, UINT uSize)
2023 LPMIDIOPENDESC lpDesc;
2025 TRACE(mmsys, "(%04X, %p, %d)\n", hMidiOut, lpMidiOutHdr, uSize);
2027 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2028 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2029 lpMidiOutHdr->reserved = (DWORD)lpMidiOutHdr->lpData;
2030 return modMessage(lpDesc->wDevID, MODM_PREPARE, lpDesc->dwInstance,
2031 (DWORD)lpMidiOutHdr, (DWORD)uSize);
2034 /**************************************************************************
2035 * midiOutPrepareHeader [MMSYSTEM.206]
2037 UINT16 WINAPI midiOutPrepareHeader16(HMIDIOUT16 hMidiOut,
2038 MIDIHDR16* lpMidiOutHdr, UINT16 uSize)
2040 LPMIDIOPENDESC lpDesc;
2042 TRACE(mmsys, "(%04X, %p, %d)\n", hMidiOut, lpMidiOutHdr, uSize);
2044 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2045 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2046 lpMidiOutHdr->reserved = (DWORD)PTR_SEG_TO_LIN(lpMidiOutHdr->lpData);
2047 return modMessage(lpDesc->wDevID, MODM_PREPARE, lpDesc->dwInstance,
2048 (DWORD)lpMidiOutHdr, (DWORD)uSize);
2051 /**************************************************************************
2052 * midiOutUnprepareHeader [WINMM.89]
2054 UINT WINAPI midiOutUnprepareHeader(HMIDIOUT hMidiOut,
2055 MIDIHDR16* lpMidiOutHdr, UINT uSize)
2057 return midiOutUnprepareHeader16(hMidiOut, lpMidiOutHdr,uSize);
2060 /**************************************************************************
2061 * midiOutUnprepareHeader [MMSYSTEM.207]
2063 UINT16 WINAPI midiOutUnprepareHeader16(HMIDIOUT16 hMidiOut,
2064 MIDIHDR16* lpMidiOutHdr, UINT16 uSize)
2066 LPMIDIOPENDESC lpDesc;
2068 TRACE(mmsys, "(%04X, %p, %d)\n", hMidiOut, lpMidiOutHdr, uSize);
2070 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2071 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2072 return modMessage(lpDesc->wDevID, MODM_UNPREPARE, lpDesc->dwInstance,
2073 (DWORD)lpMidiOutHdr, (DWORD)uSize);
2076 /**************************************************************************
2077 * midiOutShortMsg [WINMM.88]
2079 UINT WINAPI midiOutShortMsg(HMIDIOUT hMidiOut, DWORD dwMsg)
2081 return midiOutShortMsg16(hMidiOut, dwMsg);
2084 /**************************************************************************
2085 * midiOutShortMsg [MMSYSTEM.208]
2087 UINT16 WINAPI midiOutShortMsg16(HMIDIOUT16 hMidiOut, DWORD dwMsg)
2089 LPMIDIOPENDESC lpDesc;
2091 TRACE(mmsys, "(%04X, %08lX)\n", hMidiOut, dwMsg);
2093 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2094 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2095 return modMessage(lpDesc->wDevID, MODM_DATA, lpDesc->dwInstance, dwMsg, 0L);
2098 /**************************************************************************
2099 * midiOutLongMsg [WINMM.82]
2101 UINT WINAPI midiOutLongMsg(HMIDIOUT hMidiOut,
2102 MIDIHDR16* lpMidiOutHdr, UINT uSize)
2104 return midiOutLongMsg16(hMidiOut, lpMidiOutHdr,uSize);
2107 /**************************************************************************
2108 * midiOutLongMsg [MMSYSTEM.209]
2110 UINT16 WINAPI midiOutLongMsg16(HMIDIOUT16 hMidiOut,
2111 MIDIHDR16* lpMidiOutHdr, UINT16 uSize)
2113 LPMIDIOPENDESC lpDesc;
2115 TRACE(mmsys, "(%04X, %p, %d)\n", hMidiOut, lpMidiOutHdr, uSize);
2117 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2118 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2119 return modMessage(lpDesc->wDevID, MODM_LONGDATA, lpDesc->dwInstance,
2120 (DWORD)lpMidiOutHdr, (DWORD)uSize);
2123 /**************************************************************************
2124 * midiOutReset [WINMM.86]
2126 UINT WINAPI midiOutReset(HMIDIOUT hMidiOut)
2128 return midiOutReset16(hMidiOut);
2131 /**************************************************************************
2132 * midiOutReset [MMSYSTEM.210]
2134 UINT16 WINAPI midiOutReset16(HMIDIOUT16 hMidiOut)
2136 LPMIDIOPENDESC lpDesc;
2138 TRACE(mmsys, "(%04X)\n", hMidiOut);
2140 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2141 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2142 return modMessage(lpDesc->wDevID, MODM_RESET, lpDesc->dwInstance, 0L, 0L);
2145 /**************************************************************************
2146 * midiOutGetVolume [WINM.81]
2148 UINT WINAPI midiOutGetVolume(UINT uDeviceID, DWORD* lpdwVolume)
2150 return midiOutGetVolume16(uDeviceID, lpdwVolume);
2153 /**************************************************************************
2154 * midiOutGetVolume [MMSYSTEM.211]
2156 UINT16 WINAPI midiOutGetVolume16(UINT16 uDeviceID, DWORD* lpdwVolume)
2158 TRACE(mmsys, "(%04X, %p);\n", uDeviceID, lpdwVolume);
2159 return modMessage(uDeviceID, MODM_GETVOLUME, 0L, (DWORD)lpdwVolume, 0L);
2162 /**************************************************************************
2163 * midiOutSetVolume [WINMM.87]
2165 UINT WINAPI midiOutSetVolume(UINT uDeviceID, DWORD dwVolume)
2167 return midiOutSetVolume16(uDeviceID, dwVolume);
2170 /**************************************************************************
2171 * midiOutSetVolume [MMSYSTEM.212]
2173 UINT16 WINAPI midiOutSetVolume16(UINT16 uDeviceID, DWORD dwVolume)
2175 TRACE(mmsys, "(%04X, %08lX);\n", uDeviceID, dwVolume);
2176 return modMessage(uDeviceID, MODM_SETVOLUME, 0L, dwVolume, 0L);
2179 /**************************************************************************
2180 * midiOutCachePatches [WINMM.73]
2182 UINT WINAPI midiOutCachePatches(HMIDIOUT hMidiOut, UINT uBank,
2183 WORD* lpwPatchArray, UINT uFlags)
2185 return midiOutCachePatches16(hMidiOut,uBank, lpwPatchArray,uFlags);
2188 /**************************************************************************
2189 * midiOutCachePatches [MMSYSTEM.213]
2191 UINT16 WINAPI midiOutCachePatches16(HMIDIOUT16 hMidiOut, UINT16 uBank,
2192 WORD* lpwPatchArray, UINT16 uFlags)
2194 /* not really necessary to support this */
2195 FIXME(mmsys, "not supported yet\n");
2196 return MMSYSERR_NOTSUPPORTED;
2199 /**************************************************************************
2200 * midiOutCacheDrumPatches [WINMM.72]
2202 UINT WINAPI midiOutCacheDrumPatches(HMIDIOUT hMidiOut, UINT uPatch,
2203 WORD* lpwKeyArray, UINT uFlags)
2205 return midiOutCacheDrumPatches16(hMidiOut,uPatch, lpwKeyArray,uFlags);
2208 /**************************************************************************
2209 * midiOutCacheDrumPatches [MMSYSTEM.214]
2211 UINT16 WINAPI midiOutCacheDrumPatches16(HMIDIOUT16 hMidiOut, UINT16 uPatch,
2212 WORD* lpwKeyArray, UINT16 uFlags)
2214 FIXME(mmsys, "not supported yet\n");
2215 return MMSYSERR_NOTSUPPORTED;
2218 /**************************************************************************
2219 * midiOutGetID [WINMM.79]
2221 UINT WINAPI midiOutGetID(HMIDIOUT hMidiOut, UINT* lpuDeviceID)
2223 UINT16 xid;
2224 UINT ret;
2226 ret = midiOutGetID16(hMidiOut, &xid);
2227 *lpuDeviceID = xid;
2228 return ret;
2231 /**************************************************************************
2232 * midiOutGetID [MMSYSTEM.215]
2234 UINT16 WINAPI midiOutGetID16(HMIDIOUT16 hMidiOut, UINT16* lpuDeviceID)
2236 TRACE(mmsys, "midiOutGetID\n");
2237 return 0;
2240 /**************************************************************************
2241 * midiOutMessage [WINMM.83]
2243 DWORD WINAPI midiOutMessage(HMIDIOUT hMidiOut, UINT uMessage,
2244 DWORD dwParam1, DWORD dwParam2)
2246 LPMIDIOPENDESC lpDesc;
2248 TRACE(mmsys, "(%04X, %04X, %08lX, %08lX)\n",
2249 hMidiOut, uMessage, dwParam1, dwParam2);
2250 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2251 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2252 switch (uMessage) {
2253 case MODM_OPEN:
2254 FIXME(mmsys,"can't handle MODM_OPEN!\n");
2255 return 0;
2256 case MODM_GETDEVCAPS:
2257 return midiOutGetDevCapsA(hMidiOut, (LPMIDIOUTCAPSA)dwParam1, dwParam2);
2258 case MODM_GETNUMDEVS:
2259 case MODM_RESET:
2260 case MODM_CLOSE:
2261 case MODM_GETVOLUME:
2262 case MODM_SETVOLUME:
2263 case MODM_LONGDATA:
2264 case MODM_PREPARE:
2265 case MODM_UNPREPARE:
2266 /* no argument conversion needed */
2267 break;
2268 default:
2269 ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
2270 hMidiOut,uMessage, dwParam1, dwParam2);
2271 break;
2273 return modMessage(lpDesc->wDevID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
2276 /**************************************************************************
2277 * midiOutMessage [MMSYSTEM.216]
2279 DWORD WINAPI midiOutMessage16(HMIDIOUT16 hMidiOut, UINT16 uMessage,
2280 DWORD dwParam1, DWORD dwParam2)
2282 LPMIDIOPENDESC lpDesc;
2284 TRACE(mmsys, "(%04X, %04X, %08lX, %08lX)\n",
2285 hMidiOut, uMessage, dwParam1, dwParam2);
2286 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiOut);
2287 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2288 switch (uMessage) {
2289 case MODM_OPEN:
2290 FIXME(mmsys,"can't handle MODM_OPEN!\n");
2291 return 0;
2292 case MODM_GETNUMDEVS:
2293 case MODM_RESET:
2294 case MODM_CLOSE:
2295 case MODM_SETVOLUME:
2296 /* no argument conversion needed */
2297 break;
2298 case MODM_GETVOLUME:
2299 return midiOutGetVolume16(hMidiOut, (LPDWORD)PTR_SEG_TO_LIN(dwParam1));
2300 case MODM_LONGDATA:
2301 return midiOutLongMsg16(hMidiOut, (LPMIDIHDR16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
2302 case MODM_PREPARE:
2303 return midiOutPrepareHeader16(hMidiOut, (LPMIDIHDR16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
2304 case MODM_UNPREPARE:
2305 return midiOutUnprepareHeader16(hMidiOut, (LPMIDIHDR16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
2306 default:
2307 ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
2308 hMidiOut,uMessage, dwParam1, dwParam2);
2309 break;
2311 return modMessage(lpDesc->wDevID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
2314 /**************************************************************************
2315 * midiInGetNumDevs [WINMM.64]
2317 UINT WINAPI midiInGetNumDevs(void)
2319 return midiInGetNumDevs16();
2322 /**************************************************************************
2323 * midiInGetNumDevs [MMSYSTEM.301]
2325 UINT16 WINAPI midiInGetNumDevs16(void)
2327 UINT16 count = 0;
2328 TRACE(mmsys, "midiInGetNumDevs\n");
2329 count += midMessage(0, MIDM_GETNUMDEVS, 0L, 0L, 0L);
2330 TRACE(mmsys, "midiInGetNumDevs return %u \n", count);
2331 return count;
2334 /**************************************************************************
2335 * midiInGetDevCaps [WINMM.60]
2337 UINT WINAPI midiInGetDevCapsW(UINT uDeviceID, LPMIDIINCAPSW lpCaps, UINT uSize)
2339 MIDIINCAPS16 mic16;
2340 UINT ret = midiInGetDevCaps16(uDeviceID, &mic16,uSize);
2342 lpCaps->wMid = mic16.wMid;
2343 lpCaps->wPid = mic16.wPid;
2344 lpCaps->vDriverVersion = mic16.vDriverVersion;
2345 lstrcpyAtoW(lpCaps->szPname, mic16.szPname);
2346 lpCaps->dwSupport = mic16.dwSupport;
2347 return ret;
2350 /**************************************************************************
2351 * midiInGetDevCaps [WINMM.59]
2353 UINT WINAPI midiInGetDevCapsA(UINT uDeviceID, LPMIDIINCAPSA lpCaps, UINT uSize)
2355 MIDIINCAPS16 mic16;
2356 UINT ret = midiInGetDevCaps16(uDeviceID, &mic16,uSize);
2358 lpCaps->wMid = mic16.wMid;
2359 lpCaps->wPid = mic16.wPid;
2360 lpCaps->vDriverVersion = mic16.vDriverVersion;
2361 strcpy(lpCaps->szPname, mic16.szPname);
2362 lpCaps->dwSupport = mic16.dwSupport;
2363 return ret;
2366 /**************************************************************************
2367 * midiInGetDevCaps [MMSYSTEM.302]
2369 UINT16 WINAPI midiInGetDevCaps16(UINT16 uDeviceID,
2370 LPMIDIINCAPS16 lpCaps, UINT16 uSize)
2372 TRACE(mmsys, "midiInGetDevCaps\n");
2373 return midMessage(uDeviceID, MIDM_GETDEVCAPS, 0, (DWORD)lpCaps, uSize);
2376 /**************************************************************************
2377 * midiInGetErrorText [WINMM.62]
2379 UINT WINAPI midiInGetErrorTextW(UINT uError, LPWSTR lpText, UINT uSize)
2381 LPSTR xstr = HeapAlloc(GetProcessHeap(), 0,uSize);
2382 UINT ret = midiInGetErrorText16(uError,xstr,uSize);
2383 lstrcpyAtoW(lpText,xstr);
2384 HeapFree(GetProcessHeap(), 0,xstr);
2385 return ret;
2388 /**************************************************************************
2389 * midiInGetErrorText [WINMM.61]
2391 UINT WINAPI midiInGetErrorTextA(UINT uError, LPSTR lpText, UINT uSize)
2393 return midiInGetErrorText16(uError, lpText,uSize);
2396 /**************************************************************************
2397 * midiInGetErrorText [MMSYSTEM.303]
2399 UINT16 WINAPI midiInGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
2401 TRACE(mmsys, "midiInGetErrorText\n");
2402 return (midiGetErrorText(uError, lpText, uSize));
2405 /**************************************************************************
2406 * midiInOpen [WINMM.66]
2408 UINT WINAPI midiInOpen(HMIDIIN* lphMidiIn, UINT uDeviceID,
2409 DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
2411 HMIDIIN16 xhmid16;
2412 UINT ret = midiInOpen16(&xhmid16,uDeviceID, dwCallback, dwInstance,
2413 CALLBACK32CONV(dwFlags));
2414 if (lphMidiIn)
2415 *lphMidiIn = xhmid16;
2416 return ret;
2419 /**************************************************************************
2420 * midiInOpen [MMSYSTEM.304]
2422 UINT16 WINAPI midiInOpen16(HMIDIIN16* lphMidiIn, UINT16 uDeviceID,
2423 DWORD dwCallback, DWORD dwInstance, DWORD dwFlags)
2425 HMIDI16 hMidiIn;
2426 LPMIDIOPENDESC lpDesc;
2427 DWORD dwRet = 0;
2428 BOOL bMapperFlg = FALSE;
2430 if (lphMidiIn != NULL)
2431 *lphMidiIn = 0;
2432 TRACE(mmsys, "(%p, %d, %08lX, %08lX, %08lX);\n",
2433 lphMidiIn, uDeviceID, dwCallback, dwInstance, dwFlags);
2434 if (uDeviceID == (UINT16)MIDI_MAPPER) {
2435 TRACE(mmsys, "MIDI_MAPPER mode requested !\n");
2436 bMapperFlg = TRUE;
2437 uDeviceID = 0;
2439 hMidiIn = USER_HEAP_ALLOC(sizeof(MIDIOPENDESC));
2440 if (lphMidiIn != NULL)
2441 *lphMidiIn = hMidiIn;
2442 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2443 if (lpDesc == NULL)
2444 return MMSYSERR_NOMEM;
2445 lpDesc->hMidi = hMidiIn;
2446 lpDesc->dwCallback = dwCallback;
2447 lpDesc->dwInstance = dwInstance;
2449 while (uDeviceID < MAXMIDIDRIVERS) {
2450 dwRet = midMessage(uDeviceID, MIDM_OPEN,
2451 lpDesc->dwInstance, (DWORD)lpDesc, dwFlags);
2452 if (dwRet == MMSYSERR_NOERROR)
2453 break;
2454 if (!bMapperFlg)
2455 break;
2456 uDeviceID++;
2457 TRACE(mmsys, "MIDI_MAPPER mode ! try next driver...\n");
2459 lpDesc->wDevID = uDeviceID;
2460 return dwRet;
2463 /**************************************************************************
2464 * midiInClose [WINMM.58]
2466 UINT WINAPI midiInClose(HMIDIIN hMidiIn)
2468 return midiInClose16(hMidiIn);
2471 /**************************************************************************
2472 * midiInClose [MMSYSTEM.305]
2474 UINT16 WINAPI midiInClose16(HMIDIIN16 hMidiIn)
2476 LPMIDIOPENDESC lpDesc;
2477 TRACE(mmsys, "(%04X)\n", hMidiIn);
2478 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2479 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2480 return midMessage(lpDesc->wDevID, MIDM_CLOSE, lpDesc->dwInstance, 0L, 0L);
2483 /**************************************************************************
2484 * midiInPrepareHeader [WINMM.67]
2486 UINT WINAPI midiInPrepareHeader(HMIDIIN hMidiIn,
2487 MIDIHDR16* lpMidiInHdr, UINT uSize)
2489 LPMIDIOPENDESC lpDesc;
2491 TRACE(mmsys, "(%04X, %p, %d)\n",
2492 hMidiIn, lpMidiInHdr, uSize);
2493 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2494 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2495 lpMidiInHdr->reserved = (DWORD)lpMidiInHdr->lpData;
2496 return midMessage(lpDesc->wDevID, MIDM_PREPARE, lpDesc->dwInstance,
2497 (DWORD)lpMidiInHdr, (DWORD)uSize);
2500 /**************************************************************************
2501 * midiInPrepareHeader [MMSYSTEM.306]
2503 UINT16 WINAPI midiInPrepareHeader16(HMIDIIN16 hMidiIn,
2504 MIDIHDR16* lpMidiInHdr, UINT16 uSize)
2506 LPMIDIOPENDESC lpDesc;
2508 TRACE(mmsys, "(%04X, %p, %d)\n",
2509 hMidiIn, lpMidiInHdr, uSize);
2510 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2511 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2512 lpMidiInHdr->reserved = (DWORD)PTR_SEG_TO_LIN(lpMidiInHdr->lpData);
2513 return midMessage(lpDesc->wDevID, MIDM_PREPARE, lpDesc->dwInstance,
2514 (DWORD)lpMidiInHdr, (DWORD)uSize);
2517 /**************************************************************************
2518 * midiInUnprepareHeader [WINMM.71]
2520 UINT WINAPI midiInUnprepareHeader(HMIDIIN hMidiIn,
2521 MIDIHDR16* lpMidiInHdr, UINT uSize)
2523 return midiInUnprepareHeader16(hMidiIn, lpMidiInHdr,uSize);
2526 /**************************************************************************
2527 * midiInUnprepareHeader [MMSYSTEM.307]
2529 UINT16 WINAPI midiInUnprepareHeader16(HMIDIIN16 hMidiIn,
2530 MIDIHDR16* lpMidiInHdr, UINT16 uSize)
2532 LPMIDIOPENDESC lpDesc;
2533 TRACE(mmsys, "(%04X, %p, %d)\n",
2534 hMidiIn, lpMidiInHdr, uSize);
2535 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2536 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2537 return midMessage(lpDesc->wDevID, MIDM_UNPREPARE, lpDesc->dwInstance,
2538 (DWORD)lpMidiInHdr, (DWORD)uSize);
2541 /**************************************************************************
2542 * midiInAddBuffer [WINMM.57]
2544 UINT WINAPI midiInAddBuffer(HMIDIIN hMidiIn,
2545 MIDIHDR16* lpMidiInHdr, UINT uSize)
2547 return midiInAddBuffer16(hMidiIn, lpMidiInHdr,uSize);
2550 /**************************************************************************
2551 * midiInAddBuffer [MMSYSTEM.308]
2553 UINT16 WINAPI midiInAddBuffer16(HMIDIIN16 hMidiIn,
2554 MIDIHDR16* lpMidiInHdr, UINT16 uSize)
2556 TRACE(mmsys, "midiInAddBuffer\n");
2557 return 0;
2560 /**************************************************************************
2561 * midiInStart [WINMM.69]
2563 UINT WINAPI midiInStart(HMIDIIN hMidiIn)
2565 return midiInStart16(hMidiIn);
2568 /**************************************************************************
2569 * midiInStart [MMSYSTEM.309]
2571 UINT16 WINAPI midiInStart16(HMIDIIN16 hMidiIn)
2573 LPMIDIOPENDESC lpDesc;
2575 TRACE(mmsys, "(%04X)\n", hMidiIn);
2576 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2577 if (lpDesc == NULL)
2578 return MMSYSERR_INVALHANDLE;
2579 return midMessage(lpDesc->wDevID, MIDM_START, lpDesc->dwInstance, 0L, 0L);
2582 /**************************************************************************
2583 * midiInStop [WINMM.70]
2585 UINT WINAPI midiInStop(HMIDIIN hMidiIn)
2587 return midiInStop16(hMidiIn);
2590 /**************************************************************************
2591 * midiInStop [MMSYSTEM.310]
2593 UINT16 WINAPI midiInStop16(HMIDIIN16 hMidiIn)
2595 LPMIDIOPENDESC lpDesc;
2597 TRACE(mmsys, "(%04X)\n", hMidiIn);
2598 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2599 if (lpDesc == NULL)
2600 return MMSYSERR_INVALHANDLE;
2601 return midMessage(lpDesc->wDevID, MIDM_STOP, lpDesc->dwInstance, 0L, 0L);
2604 /**************************************************************************
2605 * midiInReset [WINMM.68]
2607 UINT WINAPI midiInReset(HMIDIIN hMidiIn)
2609 return midiInReset16(hMidiIn);
2612 /**************************************************************************
2613 * midiInReset [MMSYSTEM.311]
2615 UINT16 WINAPI midiInReset16(HMIDIIN16 hMidiIn)
2617 LPMIDIOPENDESC lpDesc;
2619 TRACE(mmsys, "(%04X)\n", hMidiIn);
2620 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2621 if (lpDesc == NULL)
2622 return MMSYSERR_INVALHANDLE;
2623 return midMessage(lpDesc->wDevID, MIDM_RESET, lpDesc->dwInstance, 0L, 0L);
2626 /**************************************************************************
2627 * midiInGetID [WINMM.63]
2629 UINT WINAPI midiInGetID(HMIDIIN hMidiIn, UINT* lpuDeviceID)
2631 LPMIDIOPENDESC lpDesc;
2633 TRACE(mmsys, "(%04X, %p)\n", hMidiIn, lpuDeviceID);
2634 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2635 if (lpDesc == NULL)
2636 return MMSYSERR_INVALHANDLE;
2637 if (lpuDeviceID == NULL)
2638 return MMSYSERR_INVALPARAM;
2639 *lpuDeviceID = lpDesc->wDevID;
2641 return MMSYSERR_NOERROR;
2644 /**************************************************************************
2645 * midiInGetID [MMSYSTEM.312]
2647 UINT16 WINAPI midiInGetID16(HMIDIIN16 hMidiIn, UINT16* lpuDeviceID)
2649 LPMIDIOPENDESC lpDesc;
2651 TRACE(mmsys, "(%04X, %p)\n", hMidiIn, lpuDeviceID);
2652 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2653 if (lpDesc == NULL)
2654 return MMSYSERR_INVALHANDLE;
2655 if (lpuDeviceID == NULL)
2656 return MMSYSERR_INVALPARAM;
2657 *lpuDeviceID = lpDesc->wDevID;
2659 return MMSYSERR_NOERROR;
2662 /**************************************************************************
2663 * midiInMessage [WINMM.65]
2665 DWORD WINAPI midiInMessage(HMIDIIN hMidiIn, UINT uMessage,
2666 DWORD dwParam1, DWORD dwParam2)
2668 LPMIDIOPENDESC lpDesc;
2670 TRACE(mmsys, "(%04X, %04X, %08lX, %08lX)\n",
2671 hMidiIn, uMessage, dwParam1, dwParam2);
2672 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2673 if (lpDesc == NULL)
2674 return MMSYSERR_INVALHANDLE;
2676 switch (uMessage) {
2677 case MIDM_OPEN:
2678 FIXME(mmsys,"can't handle MIDM_OPEN!\n");
2679 return 0;
2680 case MIDM_GETDEVCAPS:
2681 return midiInGetDevCapsA(hMidiIn, (LPMIDIINCAPSA)dwParam1, dwParam2);
2682 case MIDM_GETNUMDEVS:
2683 case MIDM_RESET:
2684 case MIDM_STOP:
2685 case MIDM_START:
2686 case MIDM_CLOSE:
2687 /* no argument conversion needed */
2688 break;
2689 case MIDM_PREPARE:
2690 return midiInPrepareHeader(hMidiIn, (LPMIDIHDR16)dwParam1, dwParam2);
2691 case MIDM_UNPREPARE:
2692 return midiInUnprepareHeader(hMidiIn, (LPMIDIHDR16)dwParam1, dwParam2);
2693 case MIDM_ADDBUFFER:
2694 return midiInAddBuffer(hMidiIn, (LPMIDIHDR16)dwParam1, dwParam2);
2695 default:
2696 ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
2697 hMidiIn,uMessage, dwParam1, dwParam2);
2698 break;
2700 return midMessage(0, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
2703 /**************************************************************************
2704 * midiInMessage [MMSYSTEM.313]
2706 DWORD WINAPI midiInMessage16(HMIDIIN16 hMidiIn, UINT16 uMessage,
2707 DWORD dwParam1, DWORD dwParam2)
2709 LPMIDIOPENDESC lpDesc;
2711 TRACE(mmsys, "(%04X, %04X, %08lX, %08lX)\n", hMidiIn, uMessage, dwParam1, dwParam2);
2713 lpDesc = (LPMIDIOPENDESC) USER_HEAP_LIN_ADDR(hMidiIn);
2714 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
2715 switch (uMessage) {
2716 case MIDM_OPEN:
2717 WARN(mmsys,"can't handle MIDM_OPEN!\n");
2718 return 0;
2719 case MIDM_GETDEVCAPS:
2720 return midiInGetDevCaps16(hMidiIn, (LPMIDIINCAPS16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
2721 case MIDM_GETNUMDEVS:
2722 case MIDM_RESET:
2723 case MIDM_STOP:
2724 case MIDM_START:
2725 case MIDM_CLOSE:
2726 /* no argument conversion needed */
2727 break;
2728 case MIDM_PREPARE:
2729 return midiInPrepareHeader16(hMidiIn, (LPMIDIHDR16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
2730 case MIDM_UNPREPARE:
2731 return midiInUnprepareHeader16(hMidiIn, (LPMIDIHDR16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
2732 case MIDM_ADDBUFFER:
2733 return midiInAddBuffer16(hMidiIn, (LPMIDIHDR16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
2734 default:
2735 ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
2736 hMidiIn,uMessage, dwParam1, dwParam2);
2737 break;
2739 return midMessage(0, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
2742 #define MIDI_STREAM_MAGIC 0xC9080F17
2744 typedef struct {
2745 DWORD dwMagic;
2746 HMIDIOUT hDevice;
2747 /* thread ID */
2748 DWORD dwTempo;
2749 DWORD dwTimeDiv;
2750 DWORD dwMS;
2751 DWORD dwStatus;
2752 LPMIDIHDR lpMidiHdr;
2753 } WINE_MIDIStream;
2755 /**************************************************************************
2756 * MMSYSTEM_MidiStreamPlayer [internal]
2758 static void WINE_UNUSED MMSYSTEM_MidiStreamPlayer(WINE_MIDIStream* ms)
2760 /* FIXME: should I sleep a bit when there is no pending lpMidiHdr ?
2761 * => provide a better synchronization system
2762 * midiStreamPause/midiStreamRestart should freeze/thaw this thread
2763 * global resource should guard access to ms->lpMidiHdr list, or
2764 * use a MB to send new LPMIDIHDR
2765 * an empty ms->lpMidiHdr list should freeze this thread
2767 for (;;) {
2768 if (ms->dwStatus && ms->lpMidiHdr) {
2769 LPMIDIEVENT me = (LPMIDIEVENT)(ms->lpMidiHdr->lpData + ms->lpMidiHdr->dwOffset);
2771 FIXME(mmsys, "Should wait for current time to be in sync with me->dwDeltaTime\n");
2773 if (me->dwEvent & MEVT_F_CALLBACK) {
2774 WARN(mmsys, "Should generate callback when encountering F_CALLBACK flagged midi events...\n");
2776 switch (MEVT_EVENTTYPE(me->dwEvent)) {
2777 case MEVT_COMMENT:
2778 /* do nothing, skip bytes */
2779 break;
2780 case MEVT_LONGMSG:
2781 WARN(mmsys, "NIY: sending Sysex Event");
2782 break;
2783 case MEVT_NOP:
2784 break;
2785 case MEVT_SHORTMSG:
2786 midiOutShortMsg(ms->hDevice, MEVT_EVENTPARM(me->dwEvent));
2787 break;
2788 case MEVT_TEMPO:
2789 ms->dwTempo = MEVT_EVENTPARM(me->dwEvent);
2790 break;
2791 case MEVT_VERSION:
2792 break;
2794 ms->lpMidiHdr->dwOffset += sizeof(MIDIEVENT);
2795 if (me->dwEvent & MEVT_F_LONG) {
2796 ms->lpMidiHdr->dwOffset += MEVT_EVENTPARM(me->dwEvent);
2798 if (ms->lpMidiHdr->dwOffset >= ms->lpMidiHdr->dwBufferLength) {
2799 ms->lpMidiHdr->dwFlags |= MHDR_DONE;
2800 ms->lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
2801 ms->lpMidiHdr = (LPMIDIHDR)ms->lpMidiHdr->lpNext;
2802 WARN(mmsys, "Should generate callback when done with MIDIHDR...\n");
2804 FIXME(mmsys, "Should accordingly update ms->dwMS with me->dwDeltaTime\n");
2809 /**************************************************************************
2810 * midiStreamClose [WINMM.90]
2812 MMRESULT WINAPI midiStreamClose(HMIDISTRM hms)
2814 WINE_MIDIStream* ms;
2816 TRACE(midi, "(%08x)!\n", hms);
2818 ms = (WINE_MIDIStream*)hms;
2819 if (!ms || ms->dwMagic != MIDI_STREAM_MAGIC)
2820 return MMSYSERR_INVALHANDLE;
2822 free(ms);
2824 return MMSYSERR_NOTSUPPORTED;
2827 /**************************************************************************
2828 * midiStreamOpen [WINMM.91]
2830 MMRESULT WINAPI midiStreamOpen(HMIDISTRM* phms, LPUINT lpuDeviceID,
2831 DWORD cMidi, DWORD dwCallback,
2832 DWORD dwInstance, DWORD fdwOpen)
2834 WINE_MIDIStream* ms;
2836 TRACE(midi, "(%p,%p,%ld, 0x%08lx, 0x%08lx, 0x%08lx), stub!\n",
2837 phms, lpuDeviceID,cMidi, dwCallback, dwInstance, fdwOpen);
2839 if (cMidi != 1 || phms == NULL || lpuDeviceID == NULL)
2840 return MMSYSERR_INVALPARAM;
2842 ms = malloc(sizeof(WINE_MIDIStream));
2843 *phms = (HMIDISTRM)ms;
2844 ms->dwMagic = MIDI_STREAM_MAGIC;
2845 ms->dwTempo = 50000; /* FIXME */
2846 ms->dwTimeDiv = 1; /* FIXME */
2847 ms->dwMS = 0;
2848 ms->dwStatus = 0;
2850 /* FIXME is this correct ? */
2851 *lpuDeviceID = 0;
2852 /* FIXME is this correct ? */
2853 return midiOutOpen(&(ms->hDevice), *lpuDeviceID, dwCallback, dwInstance, fdwOpen);
2856 /**************************************************************************
2857 * midiStreamOut [WINMM.92]
2859 MMRESULT WINAPI midiStreamOut(HMIDISTRM hms, LPMIDIHDR16 lpMidiHdr, UINT cbMidiHdr)
2861 FIXME(midi, "(%08x, %p, %u) stub!\n", hms, lpMidiHdr, cbMidiHdr);
2862 return MMSYSERR_NOTSUPPORTED;
2865 /**************************************************************************
2866 * midiStreamPause [WINMM.93]
2868 MMRESULT WINAPI midiStreamPause(HMIDISTRM hms)
2870 WINE_MIDIStream* ms;
2872 TRACE(midi, "(%08x)!\n", hms);
2874 ms = (WINE_MIDIStream*)hms;
2875 if (!ms || ms->dwMagic != MIDI_STREAM_MAGIC)
2876 return MMSYSERR_INVALHANDLE;
2878 ms->dwStatus = 0;
2879 return MMSYSERR_NOERROR;
2882 /**************************************************************************
2883 * midiStreamPosition [WINMM.94]
2885 MMRESULT WINAPI midiStreamPosition(HMIDISTRM hms, LPMMTIME lpMMT, UINT cbmmt)
2887 WINE_MIDIStream* ms;
2888 DWORD ret = MMSYSERR_NOERROR;
2890 FIXME(midi, "(%08x, %p, %u) stub!\n", hms, lpMMT, cbmmt);
2892 ms = (WINE_MIDIStream*)hms;
2894 if (!ms || ms->dwMagic != MIDI_STREAM_MAGIC) {
2895 ret = MMSYSERR_INVALHANDLE;
2896 } else if (lpMMT == NULL || cbmmt != sizeof(MMTIME)) {
2897 ret = MMSYSERR_INVALPARAM;
2898 } else {
2899 switch (lpMMT->wType) {
2900 case TIME_MS:
2901 lpMMT->u.ms = ms->dwMS;
2902 break;
2903 default:
2904 lpMMT->wType = TIME_MS;
2905 ret = MMSYSERR_INVALPARAM;
2908 return ret;
2911 /**************************************************************************
2912 * midiStreamProperty [WINMM.95]
2914 MMRESULT WINAPI midiStreamProperty(HMIDISTRM hms, LPBYTE lpPropData, DWORD dwProperty)
2916 WINE_MIDIStream* ms = (WINE_MIDIStream*)hms;
2917 MMRESULT ret = MMSYSERR_NOERROR;
2919 TRACE(midi, "(%08x, %p, %lx)\n", hms, lpPropData, dwProperty);
2921 if (!ms || ms->dwMagic != MIDI_STREAM_MAGIC) {
2922 ret = MMSYSERR_INVALHANDLE;
2923 } else if ((dwProperty & (MIDIPROP_GET|MIDIPROP_SET)) == 0) {
2924 return MMSYSERR_INVALPARAM;
2925 } else if (dwProperty & MIDIPROP_TEMPO) {
2926 MIDIPROPTEMPO* mpt = (MIDIPROPTEMPO*)lpPropData;
2928 if (sizeof(MIDIPROPTEMPO) != mpt->cbStruct) {
2929 ret = MMSYSERR_INVALPARAM;
2930 } else if (dwProperty & MIDIPROP_GET) {
2931 ms->dwTempo = mpt->dwTempo;
2932 } else if (dwProperty & MIDIPROP_SET) {
2933 mpt->dwTempo = ms->dwTempo;
2935 } else if (dwProperty & MIDIPROP_TIMEDIV) {
2936 MIDIPROPTIMEDIV* mptd = (MIDIPROPTIMEDIV*)lpPropData;
2938 if (sizeof(MIDIPROPTIMEDIV) != mptd->cbStruct) {
2939 ret = MMSYSERR_INVALPARAM;
2940 } else if (dwProperty & MIDIPROP_GET) {
2941 ms->dwTimeDiv = mptd->dwTimeDiv;
2942 } else if (dwProperty & MIDIPROP_SET) {
2943 mptd->dwTimeDiv = ms->dwTimeDiv;
2945 } else {
2946 ret = MMSYSERR_INVALPARAM;
2949 return ret;
2952 /**************************************************************************
2953 * midiStreamRestart [WINMM.96]
2955 MMRESULT WINAPI midiStreamRestart(HMIDISTRM hms)
2957 WINE_MIDIStream* ms;
2959 TRACE(midi, "(%08x)!\n", hms);
2961 ms = (WINE_MIDIStream*)hms;
2962 if (!ms || ms->dwMagic != MIDI_STREAM_MAGIC)
2963 return MMSYSERR_INVALHANDLE;
2965 ms->dwStatus = 1;
2966 return MMSYSERR_NOERROR;
2969 /**************************************************************************
2970 * midiStreamStop [WINMM.97]
2972 MMRESULT WINAPI midiStreamStop(HMIDISTRM hms)
2974 FIXME(midi, "(%08x stub!)\n", hms);
2975 return MMSYSERR_NOTSUPPORTED;
2978 /**************************************************************************
2979 * midiStreamClose [MMSYSTEM.252]
2981 MMRESULT16 WINAPI midiStreamClose16(HMIDISTRM16 hms)
2983 return midiStreamClose(hms);
2986 /**************************************************************************
2987 * midiStreamOpen [MMSYSTEM.251]
2989 MMRESULT16 WINAPI midiStreamOpen16(HMIDISTRM16* phms, LPUINT16 devid,
2990 DWORD cMidi, DWORD dwCallback,
2991 DWORD dwInstance, DWORD fdwOpen)
2993 HMIDISTRM hms32;
2994 MMRESULT ret;
2995 UINT devid32;
2997 if (!phms || !devid)
2998 return MMSYSERR_INVALPARAM;
2999 devid32 = *devid;
3000 ret = midiStreamOpen(&hms32, &devid32, cMidi, dwCallback, dwInstance, fdwOpen);
3001 *phms = hms32;
3002 *devid = devid32;
3003 return ret;
3006 /**************************************************************************
3007 * midiStreamOut [MMSYSTEM.254]
3009 MMRESULT16 WINAPI midiStreamOut16(HMIDISTRM16 hms, LPMIDIHDR16 lpMidiHdr, UINT16 cbMidiHdr)
3011 return midiStreamOut(hms, lpMidiHdr, cbMidiHdr);
3014 /**************************************************************************
3015 * midiStreamPause [MMSYSTEM.255]
3017 MMRESULT16 WINAPI midiStreamPause16(HMIDISTRM16 hms)
3019 return midiStreamPause(hms);
3022 /**************************************************************************
3023 * midiStreamPosition [MMSYSTEM.253]
3025 MMRESULT16 WINAPI midiStreamPosition16(HMIDISTRM16 hms, LPMMTIME16 lpmmt, UINT16 cbmmt)
3027 MMTIME mmt32;
3028 MMRESULT ret;
3030 if (!lpmmt)
3031 return MMSYSERR_INVALPARAM;
3032 MMSYSTEM_MMTIME16to32(&mmt32, lpmmt);
3033 ret = midiStreamPosition(hms, &mmt32, cbmmt);
3034 MMSYSTEM_MMTIME32to16(lpmmt, &mmt32);
3035 return ret;
3038 /**************************************************************************
3039 * midiStreamProperty [MMSYSTEM.250]
3041 MMRESULT16 WINAPI midiStreamProperty16(HMIDISTRM16 hms, LPBYTE lpPropData, DWORD dwProperty)
3043 return midiStreamProperty(hms, lpPropData, dwProperty);
3046 /**************************************************************************
3047 * midiStreamRestart [MMSYSTEM.256]
3049 MMRESULT16 WINAPI midiStreamRestart16(HMIDISTRM16 hms)
3051 return midiStreamRestart(hms);
3054 /**************************************************************************
3055 * midiStreamStop [MMSYSTEM.257]
3057 MMRESULT16 WINAPI midiStreamStop16(HMIDISTRM16 hms)
3059 return midiStreamStop(hms);
3062 /**************************************************************************
3063 * waveOutGetNumDevs [MMSYSTEM.401]
3065 UINT WINAPI waveOutGetNumDevs()
3067 return waveOutGetNumDevs16();
3070 /**************************************************************************
3071 * waveOutGetNumDevs [WINMM.167]
3073 UINT16 WINAPI waveOutGetNumDevs16()
3075 UINT16 count = 0;
3076 TRACE(mmsys, "waveOutGetNumDevs\n");
3077 /* FIXME: I'm not sure MCI_FirstDevID() is correct */
3078 count += wodMessage(MCI_FirstDevID(), WODM_GETNUMDEVS, 0L, 0L, 0L);
3079 TRACE(mmsys, "waveOutGetNumDevs return %u \n", count);
3080 return count;
3083 /**************************************************************************
3084 * waveOutGetDevCaps [MMSYSTEM.402]
3086 UINT16 WINAPI waveOutGetDevCaps16(UINT16 uDeviceID, LPWAVEOUTCAPS16 lpCaps,
3087 UINT16 uSize)
3089 if (uDeviceID > waveOutGetNumDevs16() - 1) return MMSYSERR_BADDEVICEID;
3090 if (uDeviceID == (UINT16)WAVE_MAPPER) return MMSYSERR_BADDEVICEID; /* FIXME: do we have a wave mapper ? */
3091 TRACE(mmsys, "waveOutGetDevCaps\n");
3092 return wodMessage(uDeviceID, WODM_GETDEVCAPS, 0L, (DWORD)lpCaps, uSize);
3095 /**************************************************************************
3096 * waveOutGetDevCapsA [WINMM.162]
3098 UINT WINAPI waveOutGetDevCapsA(UINT uDeviceID, LPWAVEOUTCAPSA lpCaps,
3099 UINT uSize)
3101 WAVEOUTCAPS16 woc16;
3102 UINT16 ret = waveOutGetDevCaps16(uDeviceID, &woc16, sizeof(woc16));
3104 lpCaps->wMid = woc16.wMid;
3105 lpCaps->wPid = woc16.wPid;
3106 lpCaps->vDriverVersion = woc16.vDriverVersion;
3107 strcpy(lpCaps->szPname, woc16.szPname);
3108 lpCaps->dwFormats = woc16.dwFormats;
3109 lpCaps->wChannels = woc16.wChannels;
3110 lpCaps->dwSupport = woc16.dwSupport;
3111 return ret;
3114 /**************************************************************************
3115 * waveOutGetDevCapsW [WINMM.163]
3117 UINT WINAPI waveOutGetDevCapsW(UINT uDeviceID, LPWAVEOUTCAPSW lpCaps,
3118 UINT uSize)
3120 WAVEOUTCAPS16 woc16;
3121 UINT ret = waveOutGetDevCaps16(uDeviceID, &woc16, sizeof(woc16));
3123 lpCaps->wMid = woc16.wMid;
3124 lpCaps->wPid = woc16.wPid;
3125 lpCaps->vDriverVersion = woc16.vDriverVersion;
3126 lstrcpyAtoW(lpCaps->szPname, woc16.szPname);
3127 lpCaps->dwFormats = woc16.dwFormats;
3128 lpCaps->wChannels = woc16.wChannels;
3129 lpCaps->dwSupport = woc16.dwSupport;
3130 return ret;
3133 /**************************************************************************
3134 * waveOutGetErrorText [MMSYSTEM.403]
3136 UINT16 WINAPI waveOutGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
3138 TRACE(mmsys, "waveOutGetErrorText\n");
3139 return(waveGetErrorText(uError, lpText, uSize));
3142 /**************************************************************************
3143 * waveOutGetErrorTextA [WINMM.164]
3145 UINT WINAPI waveOutGetErrorTextA(UINT uError, LPSTR lpText, UINT uSize)
3147 return(waveOutGetErrorText16(uError, lpText, uSize));
3150 /**************************************************************************
3151 * waveOutGetErrorTextW [WINMM.165]
3153 UINT WINAPI waveOutGetErrorTextW(UINT uError, LPWSTR lpText, UINT uSize)
3155 LPSTR xstr = HeapAlloc(GetProcessHeap(), 0,uSize);
3156 UINT ret = waveOutGetErrorTextA(uError, xstr, uSize);
3158 lstrcpyAtoW(lpText,xstr);
3159 HeapFree(GetProcessHeap(), 0,xstr);
3160 return ret;
3163 /**************************************************************************
3164 * waveGetErrorText [internal]
3166 static UINT16 waveGetErrorText(UINT16 uError, LPSTR lpText, UINT16 uSize)
3168 LPSTR msgptr;
3169 TRACE(mmsys, "(%04X, %p, %d);\n",
3170 uError, lpText, uSize);
3171 if ((lpText == NULL) || (uSize < 1)) return(FALSE);
3172 lpText[0] = '\0';
3173 switch (uError) {
3174 case MMSYSERR_NOERROR:
3175 msgptr = "The specified command was carried out.";
3176 break;
3177 case MMSYSERR_ERROR:
3178 msgptr = "Undefined external error.";
3179 break;
3180 case MMSYSERR_BADDEVICEID:
3181 msgptr = "A device ID has been used that is out of range for your system.";
3182 break;
3183 case MMSYSERR_NOTENABLED:
3184 msgptr = "The driver was not enabled.";
3185 break;
3186 case MMSYSERR_ALLOCATED:
3187 msgptr = "The specified device is already in use. Wait until it is free, and then try again.";
3188 break;
3189 case MMSYSERR_INVALHANDLE:
3190 msgptr = "The specified device handle is invalid.";
3191 break;
3192 case MMSYSERR_NODRIVER:
3193 msgptr = "There is no driver installed on your system !\n";
3194 break;
3195 case MMSYSERR_NOMEM:
3196 msgptr = "Not enough memory available for this task. Quit one or more applications to increase available memory, and then try again.";
3197 break;
3198 case MMSYSERR_NOTSUPPORTED:
3199 msgptr = "This function is not supported. Use the Capabilities function to determine which functions and messages the driver supports.";
3200 break;
3201 case MMSYSERR_BADERRNUM:
3202 msgptr = "An error number was specified that is not defined in the system.";
3203 break;
3204 case MMSYSERR_INVALFLAG:
3205 msgptr = "An invalid flag was passed to a system function.";
3206 break;
3207 case MMSYSERR_INVALPARAM:
3208 msgptr = "An invalid parameter was passed to a system function.";
3209 break;
3210 case WAVERR_BADFORMAT:
3211 msgptr = "The specified format is not supported or cannot be translated. Use the Capabilities function to determine the supported formats";
3212 break;
3213 case WAVERR_STILLPLAYING:
3214 msgptr = "Cannot perform this operation while media data is still playing. Reset the device, or wait until the data is finished playing.";
3215 break;
3216 case WAVERR_UNPREPARED:
3217 msgptr = "The wave header was not prepared. Use the Prepare function to prepare the header, and then try again.";
3218 break;
3219 case WAVERR_SYNC:
3220 msgptr = "Cannot open the device without using the WAVE_ALLOWSYNC flag. Use the flag, and then try again.";
3221 break;
3222 default:
3223 msgptr = "Unknown MMSYSTEM Error !\n";
3224 break;
3226 lstrcpynA(lpText, msgptr, uSize);
3227 return TRUE;
3230 /**************************************************************************
3231 * waveOutOpen [WINMM.173]
3232 * All the args/structs have the same layout as the win16 equivalents
3234 UINT WINAPI waveOutOpen(HWAVEOUT* lphWaveOut, UINT uDeviceID,
3235 const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
3236 DWORD dwInstance, DWORD dwFlags)
3238 HWAVEOUT16 hwo16;
3239 UINT ret = waveOutOpen16(&hwo16,uDeviceID, lpFormat, dwCallback, dwInstance,
3240 CALLBACK32CONV(dwFlags));
3242 if (lphWaveOut) *lphWaveOut=hwo16;
3243 return ret;
3246 /**************************************************************************
3247 * waveOutOpen [MMSYSTEM.404]
3249 UINT16 WINAPI waveOutOpen16(HWAVEOUT16* lphWaveOut, UINT16 uDeviceID,
3250 const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
3251 DWORD dwInstance, DWORD dwFlags)
3253 HWAVEOUT16 hWaveOut;
3254 LPWAVEOPENDESC lpDesc;
3255 DWORD dwRet = 0;
3256 BOOL bMapperFlg = FALSE;
3258 TRACE(mmsys, "(%p, %d, %p, %08lX, %08lX, %08lX);\n",
3259 lphWaveOut, uDeviceID, lpFormat, dwCallback, dwInstance, dwFlags);
3260 if (dwFlags & WAVE_FORMAT_QUERY)
3261 TRACE(mmsys, "WAVE_FORMAT_QUERY requested !\n");
3262 if (uDeviceID == (UINT16)WAVE_MAPPER) {
3263 TRACE(mmsys, "WAVE_MAPPER mode requested !\n");
3264 bMapperFlg = TRUE;
3265 uDeviceID = 0;
3267 if (lpFormat == NULL) return WAVERR_BADFORMAT;
3269 hWaveOut = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
3270 if (lphWaveOut != NULL) *lphWaveOut = hWaveOut;
3271 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3272 if (lpDesc == NULL) return MMSYSERR_NOMEM;
3273 lpDesc->hWave = hWaveOut;
3274 lpDesc->lpFormat = (LPWAVEFORMAT)lpFormat; /* should the struct be copied iso pointer? */
3275 lpDesc->dwCallBack = dwCallback;
3276 lpDesc->dwInstance = dwInstance;
3277 if (uDeviceID >= MAXWAVEDRIVERS)
3278 uDeviceID = 0;
3279 while (uDeviceID < MAXWAVEDRIVERS) {
3280 dwRet = wodMessage(uDeviceID, WODM_OPEN,
3281 lpDesc->dwInstance, (DWORD)lpDesc, dwFlags);
3282 if (dwRet == MMSYSERR_NOERROR) break;
3283 if (!bMapperFlg) break;
3284 uDeviceID++;
3285 TRACE(mmsys, "WAVE_MAPPER mode ! try next driver...\n");
3287 lpDesc->uDeviceID = uDeviceID; /* save physical Device ID */
3288 if (dwFlags & WAVE_FORMAT_QUERY) {
3289 TRACE(mmsys, "End of WAVE_FORMAT_QUERY !\n");
3290 dwRet = waveOutClose(hWaveOut);
3291 if (lphWaveOut) *lphWaveOut = 0;
3293 else if (dwRet != MMSYSERR_NOERROR)
3295 USER_HEAP_FREE(hWaveOut);
3296 if (lphWaveOut) *lphWaveOut = 0;
3298 return dwRet;
3301 /**************************************************************************
3302 * waveOutClose [WINMM.161]
3304 UINT WINAPI waveOutClose(HWAVEOUT hWaveOut)
3306 return waveOutClose16(hWaveOut);
3309 /**************************************************************************
3310 * waveOutClose [MMSYSTEM.405]
3312 UINT16 WINAPI waveOutClose16(HWAVEOUT16 hWaveOut)
3314 LPWAVEOPENDESC lpDesc;
3315 DWORD dwRet = 0;
3317 TRACE(mmsys, "(%04X)\n", hWaveOut);
3319 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3320 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3321 dwRet = wodMessage(lpDesc->uDeviceID, WODM_CLOSE, lpDesc->dwInstance, 0L, 0L);
3322 USER_HEAP_FREE(hWaveOut);
3323 return dwRet;
3326 /**************************************************************************
3327 * waveOutPrepareHeader [WINMM.175]
3329 UINT WINAPI waveOutPrepareHeader(HWAVEOUT hWaveOut,
3330 WAVEHDR* lpWaveOutHdr, UINT uSize)
3332 LPWAVEOPENDESC lpDesc;
3334 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3336 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3337 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3338 lpWaveOutHdr->reserved = (DWORD)lpWaveOutHdr->lpData;
3339 return wodMessage(lpDesc->uDeviceID, WODM_PREPARE, lpDesc->dwInstance,
3340 (DWORD)lpWaveOutHdr,uSize);
3343 /**************************************************************************
3344 * waveOutPrepareHeader [MMSYSTEM.406]
3346 UINT16 WINAPI waveOutPrepareHeader16(HWAVEOUT16 hWaveOut,
3347 WAVEHDR* lpWaveOutHdr, UINT16 uSize)
3349 LPWAVEOPENDESC lpDesc;
3350 UINT16 ret;
3352 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3354 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3355 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3356 lpWaveOutHdr->reserved = (DWORD)lpWaveOutHdr->lpData;
3357 lpWaveOutHdr->lpData = PTR_SEG_TO_LIN(lpWaveOutHdr->lpData);
3358 ret = wodMessage(lpDesc->uDeviceID, WODM_PREPARE, lpDesc->dwInstance,
3359 (DWORD)lpWaveOutHdr,uSize);
3360 lpWaveOutHdr->lpData = lpWaveOutHdr->lpData;
3361 return ret;
3364 /**************************************************************************
3365 * waveOutUnprepareHeader [WINMM.181]
3367 UINT WINAPI waveOutUnprepareHeader(HWAVEOUT hWaveOut,
3368 WAVEHDR* lpWaveOutHdr, UINT uSize)
3370 LPWAVEOPENDESC lpDesc;
3372 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3374 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3375 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3376 lpWaveOutHdr->reserved = (DWORD)lpWaveOutHdr->lpData;
3377 return wodMessage(lpDesc->uDeviceID, WODM_UNPREPARE, lpDesc->dwInstance,
3378 (DWORD)lpWaveOutHdr, uSize);
3381 /**************************************************************************
3382 * waveOutUnprepareHeader [MMSYSTEM.407]
3384 UINT16 WINAPI waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut,
3385 WAVEHDR* lpWaveOutHdr, UINT16 uSize)
3387 LPWAVEOPENDESC lpDesc;
3388 UINT16 ret;
3390 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3392 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3393 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3394 lpWaveOutHdr->reserved = (DWORD)lpWaveOutHdr->lpData;
3395 lpWaveOutHdr->lpData = PTR_SEG_TO_LIN(lpWaveOutHdr->lpData);
3396 ret = wodMessage(lpDesc->uDeviceID, WODM_UNPREPARE, lpDesc->dwInstance,
3397 (DWORD)lpWaveOutHdr, uSize);
3398 lpWaveOutHdr->lpData = (LPBYTE)lpWaveOutHdr->reserved;
3399 return ret;
3402 /**************************************************************************
3403 * waveOutWrite [MMSYSTEM.408]
3405 UINT WINAPI waveOutWrite(HWAVEOUT hWaveOut, WAVEHDR* lpWaveOutHdr,
3406 UINT uSize)
3408 LPWAVEOPENDESC lpDesc;
3410 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3412 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3413 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3414 lpWaveOutHdr->reserved = (DWORD)lpWaveOutHdr->lpData;
3415 return wodMessage(lpDesc->uDeviceID, WODM_WRITE, lpDesc->dwInstance, (DWORD)lpWaveOutHdr, uSize);
3418 /**************************************************************************
3419 * waveOutWrite [MMSYSTEM.408]
3421 UINT16 WINAPI waveOutWrite16(HWAVEOUT16 hWaveOut, WAVEHDR * lpWaveOutHdr,
3422 UINT16 uSize)
3424 LPWAVEOPENDESC lpDesc;
3425 UINT16 ret;
3427 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3429 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3430 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3431 lpWaveOutHdr->reserved =(DWORD)lpWaveOutHdr->lpData;/*save original ptr*/
3432 lpWaveOutHdr->lpData = PTR_SEG_TO_LIN(lpWaveOutHdr->lpData);
3433 ret = wodMessage(lpDesc->uDeviceID, WODM_WRITE, lpDesc->dwInstance, (DWORD)lpWaveOutHdr, uSize);
3434 lpWaveOutHdr->lpData = (LPBYTE)lpWaveOutHdr->reserved;
3435 return ret;
3438 /**************************************************************************
3439 * waveOutPause [WINMM.174]
3441 UINT WINAPI waveOutPause(HWAVEOUT hWaveOut)
3443 return waveOutPause16(hWaveOut);
3446 /**************************************************************************
3447 * waveOutPause [MMSYSTEM.409]
3449 UINT16 WINAPI waveOutPause16(HWAVEOUT16 hWaveOut)
3451 LPWAVEOPENDESC lpDesc;
3453 TRACE(mmsys, "(%04X)\n", hWaveOut);
3455 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3456 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3457 return wodMessage(lpDesc->uDeviceID, WODM_PAUSE, lpDesc->dwInstance, 0L, 0L);
3460 /**************************************************************************
3461 * waveOutRestart [WINMM.177]
3463 UINT WINAPI waveOutRestart(HWAVEOUT hWaveOut)
3465 return waveOutRestart16(hWaveOut);
3468 /**************************************************************************
3469 * waveOutRestart [MMSYSTEM.410]
3471 UINT16 WINAPI waveOutRestart16(HWAVEOUT16 hWaveOut)
3473 LPWAVEOPENDESC lpDesc;
3475 TRACE(mmsys, "(%04X)\n", hWaveOut);
3477 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3478 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3479 return wodMessage(lpDesc->uDeviceID, WODM_RESTART, lpDesc->dwInstance, 0L, 0L);
3482 /**************************************************************************
3483 * waveOutReset [WINMM.176]
3485 UINT WINAPI waveOutReset(HWAVEOUT hWaveOut)
3487 return waveOutReset16(hWaveOut);
3490 /**************************************************************************
3491 * waveOutReset [MMSYSTEM.411]
3493 UINT16 WINAPI waveOutReset16(HWAVEOUT16 hWaveOut)
3495 LPWAVEOPENDESC lpDesc;
3497 TRACE(mmsys, "(%04X)\n", hWaveOut);
3499 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3500 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3501 return wodMessage(lpDesc->uDeviceID, WODM_RESET, lpDesc->dwInstance, 0L, 0L);
3504 /**************************************************************************
3505 * waveOutGetPosition [WINMM.170]
3507 UINT WINAPI waveOutGetPosition(HWAVEOUT hWaveOut, LPMMTIME lpTime,
3508 UINT uSize)
3510 MMTIME16 mmt16;
3511 UINT ret;
3513 mmt16.wType = lpTime->wType;
3514 ret = waveOutGetPosition16(hWaveOut, &mmt16, sizeof(mmt16));
3515 MMSYSTEM_MMTIME16to32(lpTime, &mmt16);
3516 return ret;
3519 /**************************************************************************
3520 * waveOutGetPosition [MMSYSTEM.412]
3522 UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut, LPMMTIME16 lpTime,
3523 UINT16 uSize)
3525 LPWAVEOPENDESC lpDesc;
3526 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpTime, uSize);
3527 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3528 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3529 return wodMessage(lpDesc->uDeviceID, WODM_GETPOS, lpDesc->dwInstance,
3530 (DWORD)lpTime, (DWORD)uSize);
3533 #define WAVEOUT_SHORTCUT_1(xx,XX,atype) \
3534 UINT WINAPI waveOut##xx(HWAVEOUT hWaveOut, atype x) \
3536 return waveOut##xx##16(hWaveOut,x); \
3538 UINT16 WINAPI waveOut##xx##16(HWAVEOUT16 hWaveOut, atype x) \
3540 LPWAVEOPENDESC lpDesc; \
3541 TRACE(mmsys, "(%04X, %08lx);\n", hWaveOut, (DWORD)x); \
3542 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut); \
3543 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; \
3544 return wodMessage(lpDesc->uDeviceID, WODM_##XX, \
3545 lpDesc->dwInstance, (DWORD)x, 0L); \
3548 WAVEOUT_SHORTCUT_1(GetPitch,GETPITCH, DWORD*)
3549 WAVEOUT_SHORTCUT_1(SetPitch,SETPITCH, DWORD)
3550 WAVEOUT_SHORTCUT_1(GetPlaybackRate,GETPLAYBACKRATE, DWORD*)
3551 WAVEOUT_SHORTCUT_1(SetPlaybackRate,SETPLAYBACKRATE, DWORD)
3553 #define WAVEOUT_SHORTCUT_2(xx,XX,atype) \
3554 UINT WINAPI waveOut##xx(UINT devid, atype x) \
3556 return waveOut##xx##16(devid,x); \
3558 UINT16 WINAPI waveOut##xx##16(UINT16 devid, atype x) \
3560 TRACE(mmsys, "(%04X, %08lx);\n", devid, (DWORD)x); \
3561 return wodMessage(devid, WODM_##XX, 0L, (DWORD)x, 0L); \
3564 WAVEOUT_SHORTCUT_2(GetVolume,GETVOLUME, DWORD*)
3565 WAVEOUT_SHORTCUT_2(SetVolume,SETVOLUME, DWORD)
3567 /**************************************************************************
3568 * waveOutBreakLoop [MMSYSTEM.419]
3570 UINT WINAPI waveOutBreakLoop(HWAVEOUT hWaveOut)
3572 return waveOutBreakLoop16(hWaveOut);
3575 /**************************************************************************
3576 * waveOutBreakLoop [MMSYSTEM.419]
3578 UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut)
3580 TRACE(mmsys, "(%04X)\n", hWaveOut);
3581 return MMSYSERR_INVALHANDLE;
3584 /**************************************************************************
3585 * waveOutGetID [MMSYSTEM.420]
3587 UINT WINAPI waveOutGetID(HWAVEOUT hWaveOut, UINT* lpuDeviceID)
3589 LPWAVEOPENDESC lpDesc;
3591 TRACE(mmsys, "(%04X, %p);\n", hWaveOut, lpuDeviceID);
3593 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3594 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3595 if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
3596 *lpuDeviceID = lpDesc->uDeviceID;
3597 return 0;
3600 /**************************************************************************
3601 * waveOutGetID [MMSYSTEM.420]
3603 UINT16 WINAPI waveOutGetID16(HWAVEOUT16 hWaveOut, UINT16* lpuDeviceID)
3605 LPWAVEOPENDESC lpDesc;
3607 TRACE(mmsys, "(%04X, %p);\n", hWaveOut, lpuDeviceID);
3609 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3610 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3611 if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
3612 *lpuDeviceID = lpDesc->uDeviceID;
3613 return 0;
3616 /**************************************************************************
3617 * waveOutMessage [MMSYSTEM.421]
3619 DWORD WINAPI waveOutMessage(HWAVEOUT hWaveOut, UINT uMessage,
3620 DWORD dwParam1, DWORD dwParam2)
3622 LPWAVEOPENDESC lpDesc;
3624 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3625 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3626 switch (uMessage) {
3627 case WODM_GETNUMDEVS:
3628 case WODM_GETPOS:
3629 case WODM_GETVOLUME:
3630 case WODM_GETPITCH:
3631 case WODM_GETPLAYBACKRATE:
3632 case WODM_SETVOLUME:
3633 case WODM_SETPITCH:
3634 case WODM_SETPLAYBACKRATE:
3635 case WODM_RESET:
3636 case WODM_PAUSE:
3637 case WODM_PREPARE:
3638 case WODM_UNPREPARE:
3639 case WODM_STOP:
3640 case WODM_CLOSE:
3641 /* no argument conversion needed */
3642 break;
3643 case WODM_WRITE:
3644 return waveOutWrite(hWaveOut, (LPWAVEHDR)dwParam1, dwParam2);
3645 case WODM_GETDEVCAPS:
3646 /* FIXME: UNICODE/ANSI? */
3647 return waveOutGetDevCapsA(hWaveOut, (LPWAVEOUTCAPSA)dwParam1, dwParam2);
3648 case WODM_OPEN:
3649 FIXME(mmsys,"can't handle WODM_OPEN, please report.\n");
3650 break;
3651 default:
3652 ERR(mmsys,"(0x%04x, 0x%04x,%08lx,%08lx): unhandled message\n",
3653 hWaveOut,uMessage, dwParam1, dwParam2);
3654 break;
3656 return wodMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
3659 /**************************************************************************
3660 * waveOutMessage [MMSYSTEM.421]
3662 DWORD WINAPI waveOutMessage16(HWAVEOUT16 hWaveOut, UINT16 uMessage,
3663 DWORD dwParam1, DWORD dwParam2)
3665 LPWAVEOPENDESC lpDesc;
3667 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3668 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3669 switch (uMessage) {
3670 case WODM_GETNUMDEVS:
3671 case WODM_SETVOLUME:
3672 case WODM_SETPITCH:
3673 case WODM_SETPLAYBACKRATE:
3674 case WODM_RESET:
3675 case WODM_PAUSE:
3676 case WODM_STOP:
3677 case WODM_CLOSE:
3678 /* no argument conversion needed */
3679 break;
3680 case WODM_GETPOS:
3681 return waveOutGetPosition16(hWaveOut, (LPMMTIME16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
3682 case WODM_GETVOLUME:
3683 return waveOutGetVolume16(hWaveOut, (LPDWORD)PTR_SEG_TO_LIN(dwParam1));
3684 case WODM_GETPITCH:
3685 return waveOutGetPitch16(hWaveOut, (LPDWORD)PTR_SEG_TO_LIN(dwParam1));
3686 case WODM_GETPLAYBACKRATE:
3687 return waveOutGetPlaybackRate16(hWaveOut, (LPDWORD)PTR_SEG_TO_LIN(dwParam1));
3688 case WODM_GETDEVCAPS:
3689 return waveOutGetDevCaps16(hWaveOut, (LPWAVEOUTCAPS16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
3690 case WODM_PREPARE:
3691 return waveOutPrepareHeader16(hWaveOut, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
3692 case WODM_UNPREPARE:
3693 return waveOutUnprepareHeader16(hWaveOut, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
3694 case WODM_WRITE:
3695 return waveOutWrite16(hWaveOut, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
3696 case WODM_OPEN:
3697 FIXME(mmsys,"can't handle WODM_OPEN, please report.\n");
3698 break;
3699 default:
3700 ERR(mmsys,"(0x%04x, 0x%04x,%08lx,%08lx): unhandled message\n",
3701 hWaveOut,uMessage, dwParam1, dwParam2);
3703 return wodMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
3706 /**************************************************************************
3707 * waveInGetNumDevs [WINMM.151]
3709 UINT WINAPI waveInGetNumDevs()
3711 return waveInGetNumDevs16();
3714 /**************************************************************************
3715 * waveInGetNumDevs [MMSYSTEM.501]
3717 UINT16 WINAPI waveInGetNumDevs16()
3719 UINT16 count = 0;
3721 TRACE(mmsys, "waveInGetNumDevs\n");
3722 count += widMessage(0, WIDM_GETNUMDEVS, 0L, 0L, 0L);
3723 TRACE(mmsys, "waveInGetNumDevs return %u \n", count);
3724 return count;
3727 /**************************************************************************
3728 * waveInGetDevCapsA [WINMM.147]
3730 UINT WINAPI waveInGetDevCapsW(UINT uDeviceID, LPWAVEINCAPSW lpCaps, UINT uSize)
3732 WAVEINCAPS16 wic16;
3733 UINT ret = waveInGetDevCaps16(uDeviceID, &wic16,uSize);
3735 lpCaps->wMid = wic16.wMid;
3736 lpCaps->wPid = wic16.wPid;
3737 lpCaps->vDriverVersion = wic16.vDriverVersion;
3738 lstrcpyAtoW(lpCaps->szPname, wic16.szPname);
3739 lpCaps->dwFormats = wic16.dwFormats;
3740 lpCaps->wChannels = wic16.wChannels;
3742 return ret;
3745 /**************************************************************************
3746 * waveInGetDevCapsA [WINMM.146]
3748 UINT WINAPI waveInGetDevCapsA(UINT uDeviceID, LPWAVEINCAPSA lpCaps, UINT uSize)
3750 WAVEINCAPS16 wic16;
3751 UINT ret = waveInGetDevCaps16(uDeviceID, &wic16,uSize);
3753 lpCaps->wMid = wic16.wMid;
3754 lpCaps->wPid = wic16.wPid;
3755 lpCaps->vDriverVersion = wic16.vDriverVersion;
3756 strcpy(lpCaps->szPname, wic16.szPname);
3757 lpCaps->dwFormats = wic16.dwFormats;
3758 lpCaps->wChannels = wic16.wChannels;
3759 return ret;
3762 /**************************************************************************
3763 * waveInGetDevCaps [MMSYSTEM.502]
3765 UINT16 WINAPI waveInGetDevCaps16(UINT16 uDeviceID, LPWAVEINCAPS16 lpCaps, UINT16 uSize)
3767 TRACE(mmsys, "waveInGetDevCaps\n");
3769 return widMessage(uDeviceID, WIDM_GETDEVCAPS, 0L, (DWORD)lpCaps, uSize);
3772 /**************************************************************************
3773 * waveInGetErrorTextA [WINMM.148]
3775 UINT WINAPI waveInGetErrorTextA(UINT uError, LPSTR lpText, UINT uSize)
3777 TRACE(mmsys, "waveInGetErrorText\n");
3778 return(waveGetErrorText(uError, lpText, uSize));
3781 /**************************************************************************
3782 * waveInGetErrorTextW [WINMM.149]
3784 UINT WINAPI waveInGetErrorTextW(UINT uError, LPWSTR lpText, UINT uSize)
3786 LPSTR txt = HeapAlloc(GetProcessHeap(), 0,uSize);
3787 UINT ret = waveGetErrorText(uError, txt, uSize);
3789 lstrcpyAtoW(lpText, txt);
3790 HeapFree(GetProcessHeap(), 0, txt);
3791 return ret;
3794 /**************************************************************************
3795 * waveInGetErrorText [MMSYSTEM.503]
3797 UINT16 WINAPI waveInGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
3799 TRACE(mmsys, "waveInGetErrorText\n");
3800 return(waveGetErrorText(uError, lpText, uSize));
3803 /**************************************************************************
3804 * waveInOpen [WINMM.154]
3806 UINT WINAPI waveInOpen(HWAVEIN* lphWaveIn, UINT uDeviceID,
3807 const LPWAVEFORMAT lpFormat, DWORD dwCallback,
3808 DWORD dwInstance, DWORD dwFlags)
3810 HWAVEIN16 hwin16;
3811 UINT ret = waveInOpen16(&hwin16,uDeviceID, lpFormat, dwCallback, dwInstance,
3812 CALLBACK32CONV(dwFlags));
3813 if (lphWaveIn) *lphWaveIn = hwin16;
3814 return ret;
3817 /**************************************************************************
3818 * waveInOpen [MMSYSTEM.504]
3820 UINT16 WINAPI waveInOpen16(HWAVEIN16* lphWaveIn, UINT16 uDeviceID,
3821 const LPWAVEFORMAT lpFormat, DWORD dwCallback,
3822 DWORD dwInstance, DWORD dwFlags)
3824 HWAVEIN16 hWaveIn;
3825 LPWAVEOPENDESC lpDesc;
3826 DWORD dwRet = 0;
3827 BOOL bMapperFlg = FALSE;
3829 TRACE(mmsys, "(%p, %d, %p, %08lX, %08lX, %08lX);\n",
3830 lphWaveIn, uDeviceID, lpFormat, dwCallback, dwInstance, dwFlags);
3831 if (dwFlags & WAVE_FORMAT_QUERY)
3832 TRACE(mmsys, "WAVE_FORMAT_QUERY requested !\n");
3833 if (uDeviceID == (UINT16)WAVE_MAPPER) {
3834 TRACE(mmsys, "WAVE_MAPPER mode requested !\n");
3835 bMapperFlg = TRUE;
3836 uDeviceID = 0;
3838 if (lpFormat == NULL) return WAVERR_BADFORMAT;
3839 hWaveIn = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
3840 if (lphWaveIn != NULL) *lphWaveIn = hWaveIn;
3841 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3842 if (lpDesc == NULL) return MMSYSERR_NOMEM;
3843 lpDesc->hWave = hWaveIn;
3844 lpDesc->lpFormat = lpFormat;
3845 lpDesc->dwCallBack = dwCallback;
3846 lpDesc->dwInstance = dwInstance;
3847 while (uDeviceID < MAXWAVEDRIVERS) {
3848 dwRet = widMessage(uDeviceID, WIDM_OPEN,
3849 lpDesc->dwInstance, (DWORD)lpDesc, 0L);
3850 if (dwRet == MMSYSERR_NOERROR) break;
3851 if (!bMapperFlg) break;
3852 uDeviceID++;
3853 TRACE(mmsys, "WAVE_MAPPER mode ! try next driver...\n");
3855 lpDesc->uDeviceID = uDeviceID;
3856 if (dwFlags & WAVE_FORMAT_QUERY) {
3857 TRACE(mmsys, "End of WAVE_FORMAT_QUERY !\n");
3858 dwRet = waveInClose16(hWaveIn);
3860 return dwRet;
3863 /**************************************************************************
3864 * waveInClose [WINMM.145]
3866 UINT WINAPI waveInClose(HWAVEIN hWaveIn)
3868 return waveInClose16(hWaveIn);
3871 /**************************************************************************
3872 * waveInClose [MMSYSTEM.505]
3874 UINT16 WINAPI waveInClose16(HWAVEIN16 hWaveIn)
3876 LPWAVEOPENDESC lpDesc;
3878 TRACE(mmsys, "(%04X)\n", hWaveIn);
3879 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3880 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3881 return widMessage(lpDesc->uDeviceID, WIDM_CLOSE, lpDesc->dwInstance, 0L, 0L);
3884 /**************************************************************************
3885 * waveInPrepareHeader [WINMM.155]
3887 UINT WINAPI waveInPrepareHeader(HWAVEIN hWaveIn,
3888 WAVEHDR* lpWaveInHdr, UINT uSize)
3890 LPWAVEOPENDESC lpDesc;
3892 TRACE(mmsys, "(%04X, %p, %u);\n",
3893 hWaveIn, lpWaveInHdr, uSize);
3894 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3895 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3896 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3897 lpWaveInHdr = lpWaveInHdr;
3898 lpWaveInHdr->lpNext = NULL;
3899 lpWaveInHdr->dwBytesRecorded = 0;
3900 TRACE(mmsys, "lpData=%p size=%lu \n",
3901 lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
3902 return widMessage(lpDesc->uDeviceID, WIDM_PREPARE, lpDesc->dwInstance,
3903 (DWORD)lpWaveInHdr, uSize);
3906 /**************************************************************************
3907 * waveInPrepareHeader [MMSYSTEM.506]
3909 UINT16 WINAPI waveInPrepareHeader16(HWAVEIN16 hWaveIn,
3910 WAVEHDR* lpWaveInHdr, UINT16 uSize)
3912 LPWAVEOPENDESC lpDesc;
3913 LPBYTE saveddata = lpWaveInHdr->lpData;
3914 UINT16 ret;
3916 TRACE(mmsys, "(%04X, %p, %u);\n",
3917 hWaveIn, lpWaveInHdr, uSize);
3918 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3919 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3920 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3921 lpWaveInHdr = lpWaveInHdr;
3922 lpWaveInHdr->lpNext = NULL;
3923 lpWaveInHdr->dwBytesRecorded = 0;
3925 TRACE(mmsys, "lpData=%p size=%lu \n",
3926 lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
3927 lpWaveInHdr->lpData = PTR_SEG_TO_LIN(lpWaveInHdr->lpData);
3928 ret = widMessage(lpDesc->uDeviceID, WIDM_PREPARE, lpDesc->dwInstance,
3929 (DWORD)lpWaveInHdr,uSize);
3930 lpWaveInHdr->lpData = saveddata;
3931 return ret;
3934 /**************************************************************************
3935 * waveInUnprepareHeader [WINMM.159]
3937 UINT WINAPI waveInUnprepareHeader(HWAVEIN hWaveIn,
3938 WAVEHDR* lpWaveInHdr, UINT uSize)
3940 LPWAVEOPENDESC lpDesc;
3942 TRACE(mmsys, "(%04X, %p, %u);\n",
3943 hWaveIn, lpWaveInHdr, uSize);
3944 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3945 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3946 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3947 /*USER_HEAP_FREE(HIWORD((DWORD)lpWaveInHdr->lpData)); FIXME */
3948 lpWaveInHdr->lpData = NULL;
3949 lpWaveInHdr->lpNext = NULL;
3950 return widMessage(lpDesc->uDeviceID, WIDM_UNPREPARE, lpDesc->dwInstance,
3951 (DWORD)lpWaveInHdr, uSize);
3954 /**************************************************************************
3955 * waveInUnprepareHeader [MMSYSTEM.507]
3957 UINT16 WINAPI waveInUnprepareHeader16(HWAVEIN16 hWaveIn,
3958 WAVEHDR* lpWaveInHdr, UINT16 uSize)
3960 LPWAVEOPENDESC lpDesc;
3962 TRACE(mmsys, "(%04X, %p, %u);\n",
3963 hWaveIn, lpWaveInHdr, uSize);
3964 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3965 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3966 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3967 /*USER_HEAP_FREE(HIWORD((DWORD)lpWaveInHdr->lpData)); FIXME */
3968 lpWaveInHdr->lpData = NULL;
3969 lpWaveInHdr->lpNext = NULL;
3970 return widMessage(lpDesc->uDeviceID, WIDM_UNPREPARE, lpDesc->dwInstance,
3971 (DWORD)lpWaveInHdr, uSize);
3974 /**************************************************************************
3975 * waveInAddBuffer [WINMM.144]
3977 UINT WINAPI waveInAddBuffer(HWAVEIN hWaveIn,
3978 WAVEHDR* lpWaveInHdr, UINT uSize)
3980 LPWAVEOPENDESC lpDesc;
3982 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
3983 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3984 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3985 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3986 lpWaveInHdr->lpNext = NULL;
3987 lpWaveInHdr->dwBytesRecorded = 0;
3988 TRACE(mmsys, "lpData=%p size=%lu \n",
3989 lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
3990 return widMessage(lpDesc->uDeviceID, WIDM_ADDBUFFER, lpDesc->dwInstance,
3991 (DWORD)lpWaveInHdr, uSize);
3995 /**************************************************************************
3996 * waveInAddBuffer [MMSYSTEM.508]
3998 UINT16 WINAPI waveInAddBuffer16(HWAVEIN16 hWaveIn,
3999 WAVEHDR* lpWaveInHdr, UINT16 uSize)
4001 LPWAVEOPENDESC lpDesc;
4002 UINT16 ret;
4004 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
4005 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4006 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4007 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
4008 lpWaveInHdr->lpNext = NULL;
4009 lpWaveInHdr->dwBytesRecorded = 0;
4010 lpWaveInHdr->lpData = PTR_SEG_TO_LIN(lpWaveInHdr->lpData);
4011 TRACE(mmsys, "lpData=%p size=%lu \n",
4012 lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
4013 ret = widMessage(lpDesc->uDeviceID, WIDM_ADDBUFFER, lpDesc->dwInstance,
4014 (DWORD)lpWaveInHdr, uSize);
4015 /*lpWaveInHdr->lpData = saveddata;*/
4016 return ret;
4019 /**************************************************************************
4020 * waveInStart [WINMM.157]
4022 UINT WINAPI waveInStart(HWAVEIN hWaveIn)
4024 return waveInStart16(hWaveIn);
4027 /**************************************************************************
4028 * waveInStart [MMSYSTEM.509]
4030 UINT16 WINAPI waveInStart16(HWAVEIN16 hWaveIn)
4032 LPWAVEOPENDESC lpDesc;
4034 TRACE(mmsys, "(%04X)\n", hWaveIn);
4035 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4036 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4037 return widMessage(lpDesc->uDeviceID, WIDM_START, lpDesc->dwInstance, 0, 0);
4040 /**************************************************************************
4041 * waveInStop [WINMM.158]
4043 UINT WINAPI waveInStop(HWAVEIN hWaveIn)
4045 return waveInStop16(hWaveIn);
4048 /**************************************************************************
4049 * waveInStop [MMSYSTEM.510]
4051 UINT16 WINAPI waveInStop16(HWAVEIN16 hWaveIn)
4053 LPWAVEOPENDESC lpDesc;
4055 TRACE(mmsys, "(%04X)\n", hWaveIn);
4056 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4057 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4058 return widMessage(lpDesc->uDeviceID, WIDM_STOP, lpDesc->dwInstance, 0L, 0L);
4061 /**************************************************************************
4062 * waveInReset [WINMM.156]
4064 UINT WINAPI waveInReset(HWAVEIN hWaveIn)
4066 return waveInReset16(hWaveIn);
4069 /**************************************************************************
4070 * waveInReset [MMSYSTEM.511]
4072 UINT16 WINAPI waveInReset16(HWAVEIN16 hWaveIn)
4074 LPWAVEOPENDESC lpDesc;
4076 TRACE(mmsys, "(%04X)\n", hWaveIn);
4077 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4078 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4079 return widMessage(lpDesc->uDeviceID, WIDM_RESET, lpDesc->dwInstance, 0, 0);
4082 /**************************************************************************
4083 * waveInGetPosition [WINMM.152]
4085 UINT WINAPI waveInGetPosition(HWAVEIN hWaveIn, LPMMTIME lpTime,
4086 UINT uSize)
4088 MMTIME16 mmt16;
4089 UINT ret;
4091 mmt16.wType = lpTime->wType;
4092 ret = waveInGetPosition16(hWaveIn, &mmt16,uSize);
4094 MMSYSTEM_MMTIME16to32(lpTime, &mmt16);
4095 return ret;
4098 /**************************************************************************
4099 * waveInGetPosition [MMSYSTEM.512]
4101 UINT16 WINAPI waveInGetPosition16(HWAVEIN16 hWaveIn, LPMMTIME16 lpTime,
4102 UINT16 uSize)
4104 LPWAVEOPENDESC lpDesc;
4106 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveIn, lpTime, uSize);
4107 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4108 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4109 return widMessage(lpDesc->uDeviceID, WIDM_GETPOS, lpDesc->dwInstance,
4110 (DWORD)lpTime, (DWORD)uSize);
4113 /**************************************************************************
4114 * waveInGetID [WINMM.150]
4116 UINT WINAPI waveInGetID(HWAVEIN hWaveIn, UINT* lpuDeviceID)
4118 LPWAVEOPENDESC lpDesc;
4120 TRACE(mmsys, "waveInGetID\n");
4121 if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
4122 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4123 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4124 *lpuDeviceID = lpDesc->uDeviceID;
4125 return 0;
4128 /**************************************************************************
4129 * waveInGetID [MMSYSTEM.513]
4131 UINT16 WINAPI waveInGetID16(HWAVEIN16 hWaveIn, UINT16* lpuDeviceID)
4133 LPWAVEOPENDESC lpDesc;
4135 TRACE(mmsys, "waveInGetID\n");
4136 if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
4137 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4138 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4139 *lpuDeviceID = lpDesc->uDeviceID;
4140 return 0;
4143 /**************************************************************************
4144 * waveInMessage [WINMM.153]
4146 DWORD WINAPI waveInMessage(HWAVEIN hWaveIn, UINT uMessage,
4147 DWORD dwParam1, DWORD dwParam2)
4149 LPWAVEOPENDESC lpDesc;
4151 FIXME(mmsys, "(%04X, %04X, %08lX, %08lX)\n",
4152 hWaveIn, uMessage, dwParam1, dwParam2);
4153 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4154 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4155 switch (uMessage) {
4156 case WIDM_OPEN:
4157 FIXME(mmsys, "cannot handle WIDM_OPEN, please report.\n");
4158 break;
4159 case WIDM_GETNUMDEVS:
4160 case WIDM_GETPOS:
4161 case WIDM_CLOSE:
4162 case WIDM_STOP:
4163 case WIDM_RESET:
4164 case WIDM_START:
4165 case WIDM_PREPARE:
4166 case WIDM_UNPREPARE:
4167 case WIDM_ADDBUFFER:
4168 case WIDM_PAUSE:
4169 /* no argument conversion needed */
4170 break;
4171 case WIDM_GETDEVCAPS:
4172 /*FIXME: ANSI/UNICODE */
4173 return waveInGetDevCapsA(hWaveIn, (LPWAVEINCAPSA)dwParam1, dwParam2);
4174 default:
4175 ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
4176 hWaveIn,uMessage, dwParam1, dwParam2);
4177 break;
4179 return widMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
4182 /**************************************************************************
4183 * waveInMessage [MMSYSTEM.514]
4185 DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
4186 DWORD dwParam1, DWORD dwParam2)
4188 LPWAVEOPENDESC lpDesc;
4190 FIXME(mmsys, "(%04X, %04X, %08lX, %08lX)\n",
4191 hWaveIn, uMessage, dwParam1, dwParam2);
4192 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4193 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4194 switch (uMessage) {
4195 case WIDM_OPEN:
4196 FIXME(mmsys,"cannot handle WIDM_OPEN, please report.\n");
4197 break;
4198 case WIDM_GETNUMDEVS:
4199 case WIDM_CLOSE:
4200 case WIDM_STOP:
4201 case WIDM_RESET:
4202 case WIDM_START:
4203 case WIDM_PAUSE:
4204 /* no argument conversion needed */
4205 break;
4206 case WIDM_GETDEVCAPS:
4207 return waveInGetDevCaps16(hWaveIn, (LPWAVEINCAPS16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
4208 case WIDM_GETPOS:
4209 return waveInGetPosition16(hWaveIn, (LPMMTIME16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
4210 case WIDM_PREPARE:
4211 return waveInPrepareHeader16(hWaveIn, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
4212 case WIDM_UNPREPARE:
4213 return waveInUnprepareHeader16(hWaveIn, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
4214 case WIDM_ADDBUFFER:
4215 return waveInAddBuffer16(hWaveIn, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
4216 default:
4217 ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
4218 hWaveIn,uMessage, dwParam1, dwParam2);
4219 break;
4221 return widMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
4224 /**************************************************************************
4225 * DrvOpen [MMSYSTEM.1100]
4227 HDRVR16 WINAPI DrvOpen(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
4229 TRACE(mmsys,"('%s','%s',%08lX);\n", lpDriverName, lpSectionName, lParam);
4231 return OpenDriver16(lpDriverName, lpSectionName, lParam);
4234 /**************************************************************************
4235 * DrvClose [MMSYSTEM.1101]
4237 LRESULT WINAPI DrvClose(HDRVR16 hDrv, LPARAM lParam1, LPARAM lParam2)
4239 TRACE(mmsys, "(%04X, %08lX, %08lX);\n", hDrv, lParam1, lParam2);
4241 return CloseDriver16(hDrv, lParam1, lParam2);
4244 /**************************************************************************
4245 * DrvSendMessage [MMSYSTEM.1102]
4247 LRESULT WINAPI DrvSendMessage(HDRVR16 hDrv, WORD msg, LPARAM lParam1,
4248 LPARAM lParam2)
4250 /* DWORD dwDriverID = 0; */
4252 FIXME(mmsys, "(%04X, %04X, %08lX, %08lX);\n", hDrv, msg, lParam1, lParam2);
4253 return MMSYSERR_NOTENABLED;
4254 /* FIXME: wrong ... */
4255 /* should known the mapping between hDrv and wDevIDs */
4256 /* MCICDAUDIO_DriverProc16(dwDriverID, hDrv, msg, lParam1, lParam2); */
4259 /**************************************************************************
4260 * DrvGetModuleHandle [MMSYSTEM.1103]
4262 HANDLE16 WINAPI DrvGetModuleHandle16(HDRVR16 hDrv)
4264 return GetDriverModuleHandle16(hDrv);
4267 /**************************************************************************
4268 * DrvDefDriverProc [MMSYSTEM.1104]
4270 LRESULT WINAPI DrvDefDriverProc(DWORD dwDriverID, HDRVR16 hDrv, WORD wMsg,
4271 DWORD dwParam1, DWORD dwParam2)
4273 /* FIXME : any mapping from 32 to 16 bit structure ? */
4274 return DefDriverProc16(dwDriverID, hDrv, wMsg, dwParam1, dwParam2);
4277 /**************************************************************************
4278 * DefDriverProc [WINMM.5]
4280 LRESULT WINAPI DefDriverProc(DWORD dwDriverIdentifier, HDRVR hDrv,
4281 UINT Msg, LPARAM lParam1, LPARAM lParam2)
4283 switch (Msg) {
4284 case DRV_LOAD:
4285 case DRV_FREE:
4286 case DRV_ENABLE:
4287 case DRV_DISABLE:
4288 return 1;
4289 case DRV_INSTALL:
4290 case DRV_REMOVE:
4291 return DRV_SUCCESS;
4292 default:
4293 return 0;
4297 /**************************************************************************
4298 * mmThreadCreate [MMSYSTEM.1120]
4300 LRESULT WINAPI mmThreadCreate16(LPVOID x1, LPWORD x2, DWORD x3, DWORD x4)
4302 FIXME(mmsys, "(%p,%p,%08lx,%08lx): stub!\n",x1,x2,x3,x4);
4303 *x2 = 0xbabe;
4304 return 0;
4307 /**************************************************************************
4308 * mmThreadSignal [MMSYSTEM.1121]
4310 LRESULT WINAPI mmThreadSignal16(HANDLE16 hnd)
4312 FIXME(mmsys,"(%04x): stub!\n", hnd);
4313 return 0;
4316 /**************************************************************************
4317 * mmThreadBlock [MMSYSTEM.1122]
4319 void WINAPI mmThreadBlock16(HANDLE16 hnd)
4321 FIXME(mmsys,"(%04x): stub!\n", hnd);
4324 /**************************************************************************
4325 * mmThreadIsCurrent [MMSYSTEM.1123]
4327 BOOL16 WINAPI mmThreadIsCurrent16(HANDLE16 hnd)
4329 FIXME(mmsys,"(%04x): stub!\n", hnd);
4330 return FALSE;
4333 /**************************************************************************
4334 * mmThreadGetTask [MMSYSTEM.1125]
4336 LRESULT WINAPI mmThreadGetTask16(HANDLE16 hnd)
4338 FIXME(mmsys,"(%04x): stub!\n", hnd);
4339 return GetCurrentTask();
4342 /**************************************************************************
4343 * mmThreadIsValid [MMSYSTEM.1124]
4345 BOOL16 WINAPI mmThreadIsValid16(HANDLE16 handle)
4347 FIXME(mmsys, "(%04x): stub!\n", handle);
4348 return 0;
4351 /**************************************************************************
4352 * mmTaskCreate [MMSYSTEM.900]
4354 * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
4355 * called upon creation with dwPmt as parameter.
4357 HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR lphnd, HINSTANCE16 *hMmTask, DWORD dwPmt)
4359 #if 1
4360 DWORD showCmd = 0x40002;
4361 LPSTR cmdline;
4362 WORD sel1, sel2;
4363 LOADPARAMS16 *lp;
4364 HINSTANCE16 ret, handle;
4366 TRACE(mmsys, "(%08lx,%p,%08lx);\n", lphnd, hMmTask, dwPmt);
4367 cmdline = (LPSTR)HeapAlloc(GetProcessHeap(), 0, 0x0d);
4368 cmdline[0] = 0x0d;
4369 (DWORD)cmdline[1] = (DWORD)lphnd;
4370 (DWORD)cmdline[5] = dwPmt;
4371 (DWORD)cmdline[9] = 0;
4373 sel1 = SELECTOR_AllocBlock(cmdline, 0x0d, SEGMENT_DATA, FALSE, FALSE);
4374 sel2 = SELECTOR_AllocBlock(&showCmd, sizeof(showCmd),
4375 SEGMENT_DATA, FALSE, FALSE);
4377 lp = (LOADPARAMS16 *)HeapAlloc(GetProcessHeap(), 0, sizeof(LOADPARAMS16));
4378 lp->hEnvironment = 0;
4379 lp->cmdLine = PTR_SEG_OFF_TO_SEGPTR(sel1, 0);
4380 lp->showCmd = PTR_SEG_OFF_TO_SEGPTR(sel2, 0);
4381 lp->reserved = 0;
4383 ret = LoadModule16("c:\\windows\\system\\mmtask.tsk", lp);
4384 TRACE(mmsys, "MMtask's handle = 0x%04x\n", ret);
4385 if (ret < 32) {
4386 if (ret)
4387 ret = 1;
4388 else
4389 ret = 2;
4390 handle = 0;
4391 } else {
4392 handle = ret;
4393 ret = 0;
4395 if (hMmTask)
4396 *hMmTask = handle;
4398 UnMapLS(PTR_SEG_OFF_TO_SEGPTR(sel2, 0));
4399 UnMapLS(PTR_SEG_OFF_TO_SEGPTR(sel1, 0));
4401 HeapFree(GetProcessHeap(), 0, lp);
4402 HeapFree(GetProcessHeap(), 0, cmdline);
4404 TRACE(mmsys, "=> 0x%04x/%d %04x\n", handle, ret, *(LPWORD)PTR_SEG_TO_LIN(lphnd));
4405 return ret;
4406 #else
4407 TRACE(mmsys, "(%p,%p,%08lx);\n", lphnd, hMmTask, x2);
4408 if (hMmTask)
4409 *hMmTask = 0xfade;
4410 return 0;
4411 #endif
4414 /**************************************************************************
4415 * mmTaskBlock [MMSYSTEM.902]
4417 void WINAPI mmTaskBlock16(HINSTANCE16 WINE_UNUSED hInst)
4419 MSG msg;
4421 do {
4422 GetMessageA(&msg, 0, 0, 0);
4423 if (msg.hwnd) {
4424 TranslateMessage(&msg);
4425 DispatchMessageA(&msg);
4427 } while (msg.message < 0x3A0);
4430 /**************************************************************************
4431 * mmTaskSignal [MMSYSTEM.903]
4433 LRESULT WINAPI mmTaskSignal16(HTASK16 ht)
4435 TRACE(mmsys,"(%04x);\n", ht);
4436 return PostAppMessageA(ht, WM_USER, 0, 0);
4439 /**************************************************************************
4440 * mmTaskYield16 [MMSYSTEM.905]
4442 void WINAPI mmTaskYield16(void)
4444 MSG msg;
4446 if (PeekMessageA(&msg, 0, 0, 0, 0)) {
4447 Yield16();
4451 /**************************************************************************
4452 * mmShowMMCPLPropertySheet [MMSYSTEM.1150]
4454 BOOL16 WINAPI mmShowMMCPLPropertySheet16(WORD w1, WORD w2, WORD w3, WORD w4, WORD w5, WORD w6, WORD w7)
4456 FIXME(mmsys, "%04x %04x %04x %04x %04x %04x %04x\n", w1, w2, w3, w4, w5, w6, w7);
4457 return TRUE;