Added int 0x09 and int 0x33.
[wine/hacks.git] / multimedia / mmsystem.c
blob4945c5ed50cf13c30be88d5efff9bc7f90585112
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);
3292 return dwRet;
3295 /**************************************************************************
3296 * waveOutClose [WINMM.161]
3298 UINT WINAPI waveOutClose(HWAVEOUT hWaveOut)
3300 return waveOutClose16(hWaveOut);
3303 /**************************************************************************
3304 * waveOutClose [MMSYSTEM.405]
3306 UINT16 WINAPI waveOutClose16(HWAVEOUT16 hWaveOut)
3308 LPWAVEOPENDESC lpDesc;
3310 TRACE(mmsys, "(%04X)\n", hWaveOut);
3312 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3313 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3314 return wodMessage(lpDesc->uDeviceID, WODM_CLOSE, lpDesc->dwInstance, 0L, 0L);
3317 /**************************************************************************
3318 * waveOutPrepareHeader [WINMM.175]
3320 UINT WINAPI waveOutPrepareHeader(HWAVEOUT hWaveOut,
3321 WAVEHDR* lpWaveOutHdr, UINT uSize)
3323 LPWAVEOPENDESC lpDesc;
3325 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3327 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3328 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3329 lpWaveOutHdr->reserved = (DWORD)lpWaveOutHdr->lpData;
3330 return wodMessage(lpDesc->uDeviceID, WODM_PREPARE, lpDesc->dwInstance,
3331 (DWORD)lpWaveOutHdr,uSize);
3334 /**************************************************************************
3335 * waveOutPrepareHeader [MMSYSTEM.406]
3337 UINT16 WINAPI waveOutPrepareHeader16(HWAVEOUT16 hWaveOut,
3338 WAVEHDR* lpWaveOutHdr, UINT16 uSize)
3340 LPWAVEOPENDESC lpDesc;
3341 UINT16 ret;
3343 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3345 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3346 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3347 lpWaveOutHdr->reserved = (DWORD)lpWaveOutHdr->lpData;
3348 lpWaveOutHdr->lpData = PTR_SEG_TO_LIN(lpWaveOutHdr->lpData);
3349 ret = wodMessage(lpDesc->uDeviceID, WODM_PREPARE, lpDesc->dwInstance,
3350 (DWORD)lpWaveOutHdr,uSize);
3351 lpWaveOutHdr->lpData = lpWaveOutHdr->lpData;
3352 return ret;
3355 /**************************************************************************
3356 * waveOutUnprepareHeader [WINMM.181]
3358 UINT WINAPI waveOutUnprepareHeader(HWAVEOUT hWaveOut,
3359 WAVEHDR* lpWaveOutHdr, UINT uSize)
3361 LPWAVEOPENDESC lpDesc;
3363 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3365 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3366 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3367 lpWaveOutHdr->reserved = (DWORD)lpWaveOutHdr->lpData;
3368 return wodMessage(lpDesc->uDeviceID, WODM_UNPREPARE, lpDesc->dwInstance,
3369 (DWORD)lpWaveOutHdr, uSize);
3372 /**************************************************************************
3373 * waveOutUnprepareHeader [MMSYSTEM.407]
3375 UINT16 WINAPI waveOutUnprepareHeader16(HWAVEOUT16 hWaveOut,
3376 WAVEHDR* lpWaveOutHdr, UINT16 uSize)
3378 LPWAVEOPENDESC lpDesc;
3379 UINT16 ret;
3381 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3383 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3384 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3385 lpWaveOutHdr->reserved = (DWORD)lpWaveOutHdr->lpData;
3386 lpWaveOutHdr->lpData = PTR_SEG_TO_LIN(lpWaveOutHdr->lpData);
3387 ret = wodMessage(lpDesc->uDeviceID, WODM_UNPREPARE, lpDesc->dwInstance,
3388 (DWORD)lpWaveOutHdr, uSize);
3389 lpWaveOutHdr->lpData = (LPBYTE)lpWaveOutHdr->reserved;
3390 return ret;
3393 /**************************************************************************
3394 * waveOutWrite [MMSYSTEM.408]
3396 UINT WINAPI waveOutWrite(HWAVEOUT hWaveOut, WAVEHDR* lpWaveOutHdr,
3397 UINT uSize)
3399 LPWAVEOPENDESC lpDesc;
3401 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3403 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3404 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3405 lpWaveOutHdr->reserved = (DWORD)lpWaveOutHdr->lpData;
3406 return wodMessage(lpDesc->uDeviceID, WODM_WRITE, lpDesc->dwInstance, (DWORD)lpWaveOutHdr, uSize);
3409 /**************************************************************************
3410 * waveOutWrite [MMSYSTEM.408]
3412 UINT16 WINAPI waveOutWrite16(HWAVEOUT16 hWaveOut, WAVEHDR * lpWaveOutHdr,
3413 UINT16 uSize)
3415 LPWAVEOPENDESC lpDesc;
3416 UINT16 ret;
3418 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpWaveOutHdr, uSize);
3420 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3421 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3422 lpWaveOutHdr->reserved =(DWORD)lpWaveOutHdr->lpData;/*save original ptr*/
3423 lpWaveOutHdr->lpData = PTR_SEG_TO_LIN(lpWaveOutHdr->lpData);
3424 ret = wodMessage(lpDesc->uDeviceID, WODM_WRITE, lpDesc->dwInstance, (DWORD)lpWaveOutHdr, uSize);
3425 lpWaveOutHdr->lpData = (LPBYTE)lpWaveOutHdr->reserved;
3426 return ret;
3429 /**************************************************************************
3430 * waveOutPause [WINMM.174]
3432 UINT WINAPI waveOutPause(HWAVEOUT hWaveOut)
3434 return waveOutPause16(hWaveOut);
3437 /**************************************************************************
3438 * waveOutPause [MMSYSTEM.409]
3440 UINT16 WINAPI waveOutPause16(HWAVEOUT16 hWaveOut)
3442 LPWAVEOPENDESC lpDesc;
3444 TRACE(mmsys, "(%04X)\n", hWaveOut);
3446 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3447 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3448 return wodMessage(lpDesc->uDeviceID, WODM_PAUSE, lpDesc->dwInstance, 0L, 0L);
3451 /**************************************************************************
3452 * waveOutRestart [WINMM.177]
3454 UINT WINAPI waveOutRestart(HWAVEOUT hWaveOut)
3456 return waveOutRestart16(hWaveOut);
3459 /**************************************************************************
3460 * waveOutRestart [MMSYSTEM.410]
3462 UINT16 WINAPI waveOutRestart16(HWAVEOUT16 hWaveOut)
3464 LPWAVEOPENDESC lpDesc;
3466 TRACE(mmsys, "(%04X)\n", hWaveOut);
3468 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3469 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3470 return wodMessage(lpDesc->uDeviceID, WODM_RESTART, lpDesc->dwInstance, 0L, 0L);
3473 /**************************************************************************
3474 * waveOutReset [WINMM.176]
3476 UINT WINAPI waveOutReset(HWAVEOUT hWaveOut)
3478 return waveOutReset16(hWaveOut);
3481 /**************************************************************************
3482 * waveOutReset [MMSYSTEM.411]
3484 UINT16 WINAPI waveOutReset16(HWAVEOUT16 hWaveOut)
3486 LPWAVEOPENDESC lpDesc;
3488 TRACE(mmsys, "(%04X)\n", hWaveOut);
3490 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3491 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3492 return wodMessage(lpDesc->uDeviceID, WODM_RESET, lpDesc->dwInstance, 0L, 0L);
3495 /**************************************************************************
3496 * waveOutGetPosition [WINMM.170]
3498 UINT WINAPI waveOutGetPosition(HWAVEOUT hWaveOut, LPMMTIME lpTime,
3499 UINT uSize)
3501 MMTIME16 mmt16;
3502 UINT ret;
3504 mmt16.wType = lpTime->wType;
3505 ret = waveOutGetPosition16(hWaveOut, &mmt16, sizeof(mmt16));
3506 MMSYSTEM_MMTIME16to32(lpTime, &mmt16);
3507 return ret;
3510 /**************************************************************************
3511 * waveOutGetPosition [MMSYSTEM.412]
3513 UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut, LPMMTIME16 lpTime,
3514 UINT16 uSize)
3516 LPWAVEOPENDESC lpDesc;
3517 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveOut, lpTime, uSize);
3518 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3519 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3520 return wodMessage(lpDesc->uDeviceID, WODM_GETPOS, lpDesc->dwInstance,
3521 (DWORD)lpTime, (DWORD)uSize);
3524 #define WAVEOUT_SHORTCUT_1(xx,XX,atype) \
3525 UINT WINAPI waveOut##xx(HWAVEOUT hWaveOut, atype x) \
3527 return waveOut##xx##16(hWaveOut,x); \
3529 UINT16 WINAPI waveOut##xx##16(HWAVEOUT16 hWaveOut, atype x) \
3531 LPWAVEOPENDESC lpDesc; \
3532 TRACE(mmsys, "(%04X, %08lx);\n", hWaveOut, (DWORD)x); \
3533 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut); \
3534 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; \
3535 return wodMessage(lpDesc->uDeviceID, WODM_##XX, \
3536 lpDesc->dwInstance, (DWORD)x, 0L); \
3539 WAVEOUT_SHORTCUT_1(GetPitch,GETPITCH, DWORD*)
3540 WAVEOUT_SHORTCUT_1(SetPitch,SETPITCH, DWORD)
3541 WAVEOUT_SHORTCUT_1(GetPlaybackRate,GETPLAYBACKRATE, DWORD*)
3542 WAVEOUT_SHORTCUT_1(SetPlaybackRate,SETPLAYBACKRATE, DWORD)
3544 #define WAVEOUT_SHORTCUT_2(xx,XX,atype) \
3545 UINT WINAPI waveOut##xx(UINT devid, atype x) \
3547 return waveOut##xx##16(devid,x); \
3549 UINT16 WINAPI waveOut##xx##16(UINT16 devid, atype x) \
3551 TRACE(mmsys, "(%04X, %08lx);\n", devid, (DWORD)x); \
3552 return wodMessage(devid, WODM_##XX, 0L, (DWORD)x, 0L); \
3555 WAVEOUT_SHORTCUT_2(GetVolume,GETVOLUME, DWORD*)
3556 WAVEOUT_SHORTCUT_2(SetVolume,SETVOLUME, DWORD)
3558 /**************************************************************************
3559 * waveOutBreakLoop [MMSYSTEM.419]
3561 UINT WINAPI waveOutBreakLoop(HWAVEOUT hWaveOut)
3563 return waveOutBreakLoop16(hWaveOut);
3566 /**************************************************************************
3567 * waveOutBreakLoop [MMSYSTEM.419]
3569 UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut)
3571 TRACE(mmsys, "(%04X)\n", hWaveOut);
3572 return MMSYSERR_INVALHANDLE;
3575 /**************************************************************************
3576 * waveOutGetID [MMSYSTEM.420]
3578 UINT WINAPI waveOutGetID(HWAVEOUT hWaveOut, UINT* lpuDeviceID)
3580 LPWAVEOPENDESC lpDesc;
3582 TRACE(mmsys, "(%04X, %p);\n", hWaveOut, lpuDeviceID);
3584 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3585 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3586 if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
3587 *lpuDeviceID = lpDesc->uDeviceID;
3588 return 0;
3591 /**************************************************************************
3592 * waveOutGetID [MMSYSTEM.420]
3594 UINT16 WINAPI waveOutGetID16(HWAVEOUT16 hWaveOut, UINT16* lpuDeviceID)
3596 LPWAVEOPENDESC lpDesc;
3598 TRACE(mmsys, "(%04X, %p);\n", hWaveOut, lpuDeviceID);
3600 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3601 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3602 if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
3603 *lpuDeviceID = lpDesc->uDeviceID;
3604 return 0;
3607 /**************************************************************************
3608 * waveOutMessage [MMSYSTEM.421]
3610 DWORD WINAPI waveOutMessage(HWAVEOUT hWaveOut, UINT uMessage,
3611 DWORD dwParam1, DWORD dwParam2)
3613 LPWAVEOPENDESC lpDesc;
3615 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3616 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3617 switch (uMessage) {
3618 case WODM_GETNUMDEVS:
3619 case WODM_GETPOS:
3620 case WODM_GETVOLUME:
3621 case WODM_GETPITCH:
3622 case WODM_GETPLAYBACKRATE:
3623 case WODM_SETVOLUME:
3624 case WODM_SETPITCH:
3625 case WODM_SETPLAYBACKRATE:
3626 case WODM_RESET:
3627 case WODM_PAUSE:
3628 case WODM_PREPARE:
3629 case WODM_UNPREPARE:
3630 case WODM_STOP:
3631 case WODM_CLOSE:
3632 /* no argument conversion needed */
3633 break;
3634 case WODM_WRITE:
3635 return waveOutWrite(hWaveOut, (LPWAVEHDR)dwParam1, dwParam2);
3636 case WODM_GETDEVCAPS:
3637 /* FIXME: UNICODE/ANSI? */
3638 return waveOutGetDevCapsA(hWaveOut, (LPWAVEOUTCAPSA)dwParam1, dwParam2);
3639 case WODM_OPEN:
3640 FIXME(mmsys,"can't handle WODM_OPEN, please report.\n");
3641 break;
3642 default:
3643 ERR(mmsys,"(0x%04x, 0x%04x,%08lx,%08lx): unhandled message\n",
3644 hWaveOut,uMessage, dwParam1, dwParam2);
3645 break;
3647 return wodMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
3650 /**************************************************************************
3651 * waveOutMessage [MMSYSTEM.421]
3653 DWORD WINAPI waveOutMessage16(HWAVEOUT16 hWaveOut, UINT16 uMessage,
3654 DWORD dwParam1, DWORD dwParam2)
3656 LPWAVEOPENDESC lpDesc;
3658 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
3659 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3660 switch (uMessage) {
3661 case WODM_GETNUMDEVS:
3662 case WODM_SETVOLUME:
3663 case WODM_SETPITCH:
3664 case WODM_SETPLAYBACKRATE:
3665 case WODM_RESET:
3666 case WODM_PAUSE:
3667 case WODM_STOP:
3668 case WODM_CLOSE:
3669 /* no argument conversion needed */
3670 break;
3671 case WODM_GETPOS:
3672 return waveOutGetPosition16(hWaveOut, (LPMMTIME16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
3673 case WODM_GETVOLUME:
3674 return waveOutGetVolume16(hWaveOut, (LPDWORD)PTR_SEG_TO_LIN(dwParam1));
3675 case WODM_GETPITCH:
3676 return waveOutGetPitch16(hWaveOut, (LPDWORD)PTR_SEG_TO_LIN(dwParam1));
3677 case WODM_GETPLAYBACKRATE:
3678 return waveOutGetPlaybackRate16(hWaveOut, (LPDWORD)PTR_SEG_TO_LIN(dwParam1));
3679 case WODM_GETDEVCAPS:
3680 return waveOutGetDevCaps16(hWaveOut, (LPWAVEOUTCAPS16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
3681 case WODM_PREPARE:
3682 return waveOutPrepareHeader16(hWaveOut, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
3683 case WODM_UNPREPARE:
3684 return waveOutUnprepareHeader16(hWaveOut, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
3685 case WODM_WRITE:
3686 return waveOutWrite16(hWaveOut, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
3687 case WODM_OPEN:
3688 FIXME(mmsys,"can't handle WODM_OPEN, please report.\n");
3689 break;
3690 default:
3691 ERR(mmsys,"(0x%04x, 0x%04x,%08lx,%08lx): unhandled message\n",
3692 hWaveOut,uMessage, dwParam1, dwParam2);
3694 return wodMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
3697 /**************************************************************************
3698 * waveInGetNumDevs [WINMM.151]
3700 UINT WINAPI waveInGetNumDevs()
3702 return waveInGetNumDevs16();
3705 /**************************************************************************
3706 * waveInGetNumDevs [MMSYSTEM.501]
3708 UINT16 WINAPI waveInGetNumDevs16()
3710 UINT16 count = 0;
3712 TRACE(mmsys, "waveInGetNumDevs\n");
3713 count += widMessage(0, WIDM_GETNUMDEVS, 0L, 0L, 0L);
3714 TRACE(mmsys, "waveInGetNumDevs return %u \n", count);
3715 return count;
3718 /**************************************************************************
3719 * waveInGetDevCapsA [WINMM.147]
3721 UINT WINAPI waveInGetDevCapsW(UINT uDeviceID, LPWAVEINCAPSW lpCaps, UINT uSize)
3723 WAVEINCAPS16 wic16;
3724 UINT ret = waveInGetDevCaps16(uDeviceID, &wic16,uSize);
3726 lpCaps->wMid = wic16.wMid;
3727 lpCaps->wPid = wic16.wPid;
3728 lpCaps->vDriverVersion = wic16.vDriverVersion;
3729 lstrcpyAtoW(lpCaps->szPname, wic16.szPname);
3730 lpCaps->dwFormats = wic16.dwFormats;
3731 lpCaps->wChannels = wic16.wChannels;
3733 return ret;
3736 /**************************************************************************
3737 * waveInGetDevCapsA [WINMM.146]
3739 UINT WINAPI waveInGetDevCapsA(UINT uDeviceID, LPWAVEINCAPSA lpCaps, UINT uSize)
3741 WAVEINCAPS16 wic16;
3742 UINT ret = waveInGetDevCaps16(uDeviceID, &wic16,uSize);
3744 lpCaps->wMid = wic16.wMid;
3745 lpCaps->wPid = wic16.wPid;
3746 lpCaps->vDriverVersion = wic16.vDriverVersion;
3747 strcpy(lpCaps->szPname, wic16.szPname);
3748 lpCaps->dwFormats = wic16.dwFormats;
3749 lpCaps->wChannels = wic16.wChannels;
3750 return ret;
3753 /**************************************************************************
3754 * waveInGetDevCaps [MMSYSTEM.502]
3756 UINT16 WINAPI waveInGetDevCaps16(UINT16 uDeviceID, LPWAVEINCAPS16 lpCaps, UINT16 uSize)
3758 TRACE(mmsys, "waveInGetDevCaps\n");
3760 return widMessage(uDeviceID, WIDM_GETDEVCAPS, 0L, (DWORD)lpCaps, uSize);
3763 /**************************************************************************
3764 * waveInGetErrorTextA [WINMM.148]
3766 UINT WINAPI waveInGetErrorTextA(UINT uError, LPSTR lpText, UINT uSize)
3768 TRACE(mmsys, "waveInGetErrorText\n");
3769 return(waveGetErrorText(uError, lpText, uSize));
3772 /**************************************************************************
3773 * waveInGetErrorTextW [WINMM.149]
3775 UINT WINAPI waveInGetErrorTextW(UINT uError, LPWSTR lpText, UINT uSize)
3777 LPSTR txt = HeapAlloc(GetProcessHeap(), 0,uSize);
3778 UINT ret = waveGetErrorText(uError, txt, uSize);
3780 lstrcpyAtoW(lpText, txt);
3781 HeapFree(GetProcessHeap(), 0, txt);
3782 return ret;
3785 /**************************************************************************
3786 * waveInGetErrorText [MMSYSTEM.503]
3788 UINT16 WINAPI waveInGetErrorText16(UINT16 uError, LPSTR lpText, UINT16 uSize)
3790 TRACE(mmsys, "waveInGetErrorText\n");
3791 return(waveGetErrorText(uError, lpText, uSize));
3794 /**************************************************************************
3795 * waveInOpen [WINMM.154]
3797 UINT WINAPI waveInOpen(HWAVEIN* lphWaveIn, UINT uDeviceID,
3798 const LPWAVEFORMAT lpFormat, DWORD dwCallback,
3799 DWORD dwInstance, DWORD dwFlags)
3801 HWAVEIN16 hwin16;
3802 UINT ret = waveInOpen16(&hwin16,uDeviceID, lpFormat, dwCallback, dwInstance,
3803 CALLBACK32CONV(dwFlags));
3804 if (lphWaveIn) *lphWaveIn = hwin16;
3805 return ret;
3808 /**************************************************************************
3809 * waveInOpen [MMSYSTEM.504]
3811 UINT16 WINAPI waveInOpen16(HWAVEIN16* lphWaveIn, UINT16 uDeviceID,
3812 const LPWAVEFORMAT lpFormat, DWORD dwCallback,
3813 DWORD dwInstance, DWORD dwFlags)
3815 HWAVEIN16 hWaveIn;
3816 LPWAVEOPENDESC lpDesc;
3817 DWORD dwRet = 0;
3818 BOOL bMapperFlg = FALSE;
3820 TRACE(mmsys, "(%p, %d, %p, %08lX, %08lX, %08lX);\n",
3821 lphWaveIn, uDeviceID, lpFormat, dwCallback, dwInstance, dwFlags);
3822 if (dwFlags & WAVE_FORMAT_QUERY)
3823 TRACE(mmsys, "WAVE_FORMAT_QUERY requested !\n");
3824 if (uDeviceID == (UINT16)WAVE_MAPPER) {
3825 TRACE(mmsys, "WAVE_MAPPER mode requested !\n");
3826 bMapperFlg = TRUE;
3827 uDeviceID = 0;
3829 if (lpFormat == NULL) return WAVERR_BADFORMAT;
3830 hWaveIn = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
3831 if (lphWaveIn != NULL) *lphWaveIn = hWaveIn;
3832 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3833 if (lpDesc == NULL) return MMSYSERR_NOMEM;
3834 lpDesc->hWave = hWaveIn;
3835 lpDesc->lpFormat = lpFormat;
3836 lpDesc->dwCallBack = dwCallback;
3837 lpDesc->dwInstance = dwInstance;
3838 while (uDeviceID < MAXWAVEDRIVERS) {
3839 dwRet = widMessage(uDeviceID, WIDM_OPEN,
3840 lpDesc->dwInstance, (DWORD)lpDesc, 0L);
3841 if (dwRet == MMSYSERR_NOERROR) break;
3842 if (!bMapperFlg) break;
3843 uDeviceID++;
3844 TRACE(mmsys, "WAVE_MAPPER mode ! try next driver...\n");
3846 lpDesc->uDeviceID = uDeviceID;
3847 if (dwFlags & WAVE_FORMAT_QUERY) {
3848 TRACE(mmsys, "End of WAVE_FORMAT_QUERY !\n");
3849 dwRet = waveInClose16(hWaveIn);
3851 return dwRet;
3854 /**************************************************************************
3855 * waveInClose [WINMM.145]
3857 UINT WINAPI waveInClose(HWAVEIN hWaveIn)
3859 return waveInClose16(hWaveIn);
3862 /**************************************************************************
3863 * waveInClose [MMSYSTEM.505]
3865 UINT16 WINAPI waveInClose16(HWAVEIN16 hWaveIn)
3867 LPWAVEOPENDESC lpDesc;
3869 TRACE(mmsys, "(%04X)\n", hWaveIn);
3870 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3871 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3872 return widMessage(lpDesc->uDeviceID, WIDM_CLOSE, lpDesc->dwInstance, 0L, 0L);
3875 /**************************************************************************
3876 * waveInPrepareHeader [WINMM.155]
3878 UINT WINAPI waveInPrepareHeader(HWAVEIN hWaveIn,
3879 WAVEHDR* lpWaveInHdr, UINT uSize)
3881 LPWAVEOPENDESC lpDesc;
3883 TRACE(mmsys, "(%04X, %p, %u);\n",
3884 hWaveIn, lpWaveInHdr, uSize);
3885 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3886 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3887 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3888 lpWaveInHdr = lpWaveInHdr;
3889 lpWaveInHdr->lpNext = NULL;
3890 lpWaveInHdr->dwBytesRecorded = 0;
3891 TRACE(mmsys, "lpData=%p size=%lu \n",
3892 lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
3893 return widMessage(lpDesc->uDeviceID, WIDM_PREPARE, lpDesc->dwInstance,
3894 (DWORD)lpWaveInHdr, uSize);
3897 /**************************************************************************
3898 * waveInPrepareHeader [MMSYSTEM.506]
3900 UINT16 WINAPI waveInPrepareHeader16(HWAVEIN16 hWaveIn,
3901 WAVEHDR* lpWaveInHdr, UINT16 uSize)
3903 LPWAVEOPENDESC lpDesc;
3904 LPBYTE saveddata = lpWaveInHdr->lpData;
3905 UINT16 ret;
3907 TRACE(mmsys, "(%04X, %p, %u);\n",
3908 hWaveIn, lpWaveInHdr, uSize);
3909 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3910 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3911 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3912 lpWaveInHdr = lpWaveInHdr;
3913 lpWaveInHdr->lpNext = NULL;
3914 lpWaveInHdr->dwBytesRecorded = 0;
3916 TRACE(mmsys, "lpData=%p size=%lu \n",
3917 lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
3918 lpWaveInHdr->lpData = PTR_SEG_TO_LIN(lpWaveInHdr->lpData);
3919 ret = widMessage(lpDesc->uDeviceID, WIDM_PREPARE, lpDesc->dwInstance,
3920 (DWORD)lpWaveInHdr,uSize);
3921 lpWaveInHdr->lpData = saveddata;
3922 return ret;
3925 /**************************************************************************
3926 * waveInUnprepareHeader [WINMM.159]
3928 UINT WINAPI waveInUnprepareHeader(HWAVEIN hWaveIn,
3929 WAVEHDR* lpWaveInHdr, UINT uSize)
3931 LPWAVEOPENDESC lpDesc;
3933 TRACE(mmsys, "(%04X, %p, %u);\n",
3934 hWaveIn, lpWaveInHdr, uSize);
3935 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3936 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3937 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3938 /*USER_HEAP_FREE(HIWORD((DWORD)lpWaveInHdr->lpData)); FIXME */
3939 lpWaveInHdr->lpData = NULL;
3940 lpWaveInHdr->lpNext = NULL;
3941 return widMessage(lpDesc->uDeviceID, WIDM_UNPREPARE, lpDesc->dwInstance,
3942 (DWORD)lpWaveInHdr, uSize);
3945 /**************************************************************************
3946 * waveInUnprepareHeader [MMSYSTEM.507]
3948 UINT16 WINAPI waveInUnprepareHeader16(HWAVEIN16 hWaveIn,
3949 WAVEHDR* lpWaveInHdr, UINT16 uSize)
3951 LPWAVEOPENDESC lpDesc;
3953 TRACE(mmsys, "(%04X, %p, %u);\n",
3954 hWaveIn, lpWaveInHdr, uSize);
3955 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3956 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3957 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3958 /*USER_HEAP_FREE(HIWORD((DWORD)lpWaveInHdr->lpData)); FIXME */
3959 lpWaveInHdr->lpData = NULL;
3960 lpWaveInHdr->lpNext = NULL;
3961 return widMessage(lpDesc->uDeviceID, WIDM_UNPREPARE, lpDesc->dwInstance,
3962 (DWORD)lpWaveInHdr, uSize);
3965 /**************************************************************************
3966 * waveInAddBuffer [WINMM.144]
3968 UINT WINAPI waveInAddBuffer(HWAVEIN hWaveIn,
3969 WAVEHDR* lpWaveInHdr, UINT uSize)
3971 LPWAVEOPENDESC lpDesc;
3973 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
3974 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3975 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3976 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3977 lpWaveInHdr->lpNext = NULL;
3978 lpWaveInHdr->dwBytesRecorded = 0;
3979 TRACE(mmsys, "lpData=%p size=%lu \n",
3980 lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
3981 return widMessage(lpDesc->uDeviceID, WIDM_ADDBUFFER, lpDesc->dwInstance,
3982 (DWORD)lpWaveInHdr, uSize);
3986 /**************************************************************************
3987 * waveInAddBuffer [MMSYSTEM.508]
3989 UINT16 WINAPI waveInAddBuffer16(HWAVEIN16 hWaveIn,
3990 WAVEHDR* lpWaveInHdr, UINT16 uSize)
3992 LPWAVEOPENDESC lpDesc;
3993 UINT16 ret;
3995 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveIn, lpWaveInHdr, uSize);
3996 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
3997 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
3998 if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE;
3999 lpWaveInHdr->lpNext = NULL;
4000 lpWaveInHdr->dwBytesRecorded = 0;
4001 lpWaveInHdr->lpData = PTR_SEG_TO_LIN(lpWaveInHdr->lpData);
4002 TRACE(mmsys, "lpData=%p size=%lu \n",
4003 lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength);
4004 ret = widMessage(lpDesc->uDeviceID, WIDM_ADDBUFFER, lpDesc->dwInstance,
4005 (DWORD)lpWaveInHdr, uSize);
4006 /*lpWaveInHdr->lpData = saveddata;*/
4007 return ret;
4010 /**************************************************************************
4011 * waveInStart [WINMM.157]
4013 UINT WINAPI waveInStart(HWAVEIN hWaveIn)
4015 return waveInStart16(hWaveIn);
4018 /**************************************************************************
4019 * waveInStart [MMSYSTEM.509]
4021 UINT16 WINAPI waveInStart16(HWAVEIN16 hWaveIn)
4023 LPWAVEOPENDESC lpDesc;
4025 TRACE(mmsys, "(%04X)\n", hWaveIn);
4026 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4027 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4028 return widMessage(lpDesc->uDeviceID, WIDM_START, lpDesc->dwInstance, 0, 0);
4031 /**************************************************************************
4032 * waveInStop [WINMM.158]
4034 UINT WINAPI waveInStop(HWAVEIN hWaveIn)
4036 return waveInStop16(hWaveIn);
4039 /**************************************************************************
4040 * waveInStop [MMSYSTEM.510]
4042 UINT16 WINAPI waveInStop16(HWAVEIN16 hWaveIn)
4044 LPWAVEOPENDESC lpDesc;
4046 TRACE(mmsys, "(%04X)\n", hWaveIn);
4047 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4048 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4049 return widMessage(lpDesc->uDeviceID, WIDM_STOP, lpDesc->dwInstance, 0L, 0L);
4052 /**************************************************************************
4053 * waveInReset [WINMM.156]
4055 UINT WINAPI waveInReset(HWAVEIN hWaveIn)
4057 return waveInReset16(hWaveIn);
4060 /**************************************************************************
4061 * waveInReset [MMSYSTEM.511]
4063 UINT16 WINAPI waveInReset16(HWAVEIN16 hWaveIn)
4065 LPWAVEOPENDESC lpDesc;
4067 TRACE(mmsys, "(%04X)\n", hWaveIn);
4068 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4069 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4070 return widMessage(lpDesc->uDeviceID, WIDM_RESET, lpDesc->dwInstance, 0, 0);
4073 /**************************************************************************
4074 * waveInGetPosition [WINMM.152]
4076 UINT WINAPI waveInGetPosition(HWAVEIN hWaveIn, LPMMTIME lpTime,
4077 UINT uSize)
4079 MMTIME16 mmt16;
4080 UINT ret;
4082 mmt16.wType = lpTime->wType;
4083 ret = waveInGetPosition16(hWaveIn, &mmt16,uSize);
4085 MMSYSTEM_MMTIME16to32(lpTime, &mmt16);
4086 return ret;
4089 /**************************************************************************
4090 * waveInGetPosition [MMSYSTEM.512]
4092 UINT16 WINAPI waveInGetPosition16(HWAVEIN16 hWaveIn, LPMMTIME16 lpTime,
4093 UINT16 uSize)
4095 LPWAVEOPENDESC lpDesc;
4097 TRACE(mmsys, "(%04X, %p, %u);\n", hWaveIn, lpTime, uSize);
4098 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4099 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4100 return widMessage(lpDesc->uDeviceID, WIDM_GETPOS, lpDesc->dwInstance,
4101 (DWORD)lpTime, (DWORD)uSize);
4104 /**************************************************************************
4105 * waveInGetID [WINMM.150]
4107 UINT WINAPI waveInGetID(HWAVEIN hWaveIn, UINT* lpuDeviceID)
4109 LPWAVEOPENDESC lpDesc;
4111 TRACE(mmsys, "waveInGetID\n");
4112 if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
4113 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4114 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4115 *lpuDeviceID = lpDesc->uDeviceID;
4116 return 0;
4119 /**************************************************************************
4120 * waveInGetID [MMSYSTEM.513]
4122 UINT16 WINAPI waveInGetID16(HWAVEIN16 hWaveIn, UINT16* lpuDeviceID)
4124 LPWAVEOPENDESC lpDesc;
4126 TRACE(mmsys, "waveInGetID\n");
4127 if (lpuDeviceID == NULL) return MMSYSERR_INVALHANDLE;
4128 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4129 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4130 *lpuDeviceID = lpDesc->uDeviceID;
4131 return 0;
4134 /**************************************************************************
4135 * waveInMessage [WINMM.153]
4137 DWORD WINAPI waveInMessage(HWAVEIN hWaveIn, UINT uMessage,
4138 DWORD dwParam1, DWORD dwParam2)
4140 LPWAVEOPENDESC lpDesc;
4142 FIXME(mmsys, "(%04X, %04X, %08lX, %08lX)\n",
4143 hWaveIn, uMessage, dwParam1, dwParam2);
4144 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4145 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4146 switch (uMessage) {
4147 case WIDM_OPEN:
4148 FIXME(mmsys, "cannot handle WIDM_OPEN, please report.\n");
4149 break;
4150 case WIDM_GETNUMDEVS:
4151 case WIDM_GETPOS:
4152 case WIDM_CLOSE:
4153 case WIDM_STOP:
4154 case WIDM_RESET:
4155 case WIDM_START:
4156 case WIDM_PREPARE:
4157 case WIDM_UNPREPARE:
4158 case WIDM_ADDBUFFER:
4159 case WIDM_PAUSE:
4160 /* no argument conversion needed */
4161 break;
4162 case WIDM_GETDEVCAPS:
4163 /*FIXME: ANSI/UNICODE */
4164 return waveInGetDevCapsA(hWaveIn, (LPWAVEINCAPSA)dwParam1, dwParam2);
4165 default:
4166 ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
4167 hWaveIn,uMessage, dwParam1, dwParam2);
4168 break;
4170 return widMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
4173 /**************************************************************************
4174 * waveInMessage [MMSYSTEM.514]
4176 DWORD WINAPI waveInMessage16(HWAVEIN16 hWaveIn, UINT16 uMessage,
4177 DWORD dwParam1, DWORD dwParam2)
4179 LPWAVEOPENDESC lpDesc;
4181 FIXME(mmsys, "(%04X, %04X, %08lX, %08lX)\n",
4182 hWaveIn, uMessage, dwParam1, dwParam2);
4183 lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
4184 if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
4185 switch (uMessage) {
4186 case WIDM_OPEN:
4187 FIXME(mmsys,"cannot handle WIDM_OPEN, please report.\n");
4188 break;
4189 case WIDM_GETNUMDEVS:
4190 case WIDM_CLOSE:
4191 case WIDM_STOP:
4192 case WIDM_RESET:
4193 case WIDM_START:
4194 case WIDM_PAUSE:
4195 /* no argument conversion needed */
4196 break;
4197 case WIDM_GETDEVCAPS:
4198 return waveInGetDevCaps16(hWaveIn, (LPWAVEINCAPS16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
4199 case WIDM_GETPOS:
4200 return waveInGetPosition16(hWaveIn, (LPMMTIME16)PTR_SEG_TO_LIN(dwParam1), dwParam2);
4201 case WIDM_PREPARE:
4202 return waveInPrepareHeader16(hWaveIn, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
4203 case WIDM_UNPREPARE:
4204 return waveInUnprepareHeader16(hWaveIn, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
4205 case WIDM_ADDBUFFER:
4206 return waveInAddBuffer16(hWaveIn, (LPWAVEHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
4207 default:
4208 ERR(mmsys,"(%04x,%04x,%08lx,%08lx): unhandled message\n",
4209 hWaveIn,uMessage, dwParam1, dwParam2);
4210 break;
4212 return widMessage(lpDesc->uDeviceID, uMessage, lpDesc->dwInstance, dwParam1, dwParam2);
4215 /**************************************************************************
4216 * DrvOpen [MMSYSTEM.1100]
4218 HDRVR16 WINAPI DrvOpen(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
4220 TRACE(mmsys,"('%s','%s',%08lX);\n", lpDriverName, lpSectionName, lParam);
4222 return OpenDriver16(lpDriverName, lpSectionName, lParam);
4225 /**************************************************************************
4226 * DrvClose [MMSYSTEM.1101]
4228 LRESULT WINAPI DrvClose(HDRVR16 hDrv, LPARAM lParam1, LPARAM lParam2)
4230 TRACE(mmsys, "(%04X, %08lX, %08lX);\n", hDrv, lParam1, lParam2);
4232 return CloseDriver16(hDrv, lParam1, lParam2);
4235 /**************************************************************************
4236 * DrvSendMessage [MMSYSTEM.1102]
4238 LRESULT WINAPI DrvSendMessage(HDRVR16 hDrv, WORD msg, LPARAM lParam1,
4239 LPARAM lParam2)
4241 /* DWORD dwDriverID = 0; */
4243 FIXME(mmsys, "(%04X, %04X, %08lX, %08lX);\n", hDrv, msg, lParam1, lParam2);
4244 return MMSYSERR_NOTENABLED;
4245 /* FIXME: wrong ... */
4246 /* should known the mapping between hDrv and wDevIDs */
4247 /* MCICDAUDIO_DriverProc16(dwDriverID, hDrv, msg, lParam1, lParam2); */
4250 /**************************************************************************
4251 * DrvGetModuleHandle [MMSYSTEM.1103]
4253 HANDLE16 WINAPI DrvGetModuleHandle16(HDRVR16 hDrv)
4255 return GetDriverModuleHandle16(hDrv);
4258 /**************************************************************************
4259 * DrvDefDriverProc [MMSYSTEM.1104]
4261 LRESULT WINAPI DrvDefDriverProc(DWORD dwDriverID, HDRVR16 hDrv, WORD wMsg,
4262 DWORD dwParam1, DWORD dwParam2)
4264 /* FIXME : any mapping from 32 to 16 bit structure ? */
4265 return DefDriverProc16(dwDriverID, hDrv, wMsg, dwParam1, dwParam2);
4268 /**************************************************************************
4269 * DefDriverProc [WINMM.5]
4271 LRESULT WINAPI DefDriverProc(DWORD dwDriverIdentifier, HDRVR hDrv,
4272 UINT Msg, LPARAM lParam1, LPARAM lParam2)
4274 switch (Msg) {
4275 case DRV_LOAD:
4276 case DRV_FREE:
4277 case DRV_ENABLE:
4278 case DRV_DISABLE:
4279 return 1;
4280 case DRV_INSTALL:
4281 case DRV_REMOVE:
4282 return DRV_SUCCESS;
4283 default:
4284 return 0;
4288 /**************************************************************************
4289 * mmThreadCreate [MMSYSTEM.1120]
4291 LRESULT WINAPI mmThreadCreate16(LPVOID x1, LPWORD x2, DWORD x3, DWORD x4)
4293 FIXME(mmsys, "(%p,%p,%08lx,%08lx): stub!\n",x1,x2,x3,x4);
4294 *x2 = 0xbabe;
4295 return 0;
4298 /**************************************************************************
4299 * mmThreadSignal [MMSYSTEM.1121]
4301 LRESULT WINAPI mmThreadSignal16(HANDLE16 hnd)
4303 FIXME(mmsys,"(%04x): stub!\n", hnd);
4304 return 0;
4307 /**************************************************************************
4308 * mmThreadBlock [MMSYSTEM.1122]
4310 void WINAPI mmThreadBlock16(HANDLE16 hnd)
4312 FIXME(mmsys,"(%04x): stub!\n", hnd);
4315 /**************************************************************************
4316 * mmThreadIsCurrent [MMSYSTEM.1123]
4318 BOOL16 WINAPI mmThreadIsCurrent16(HANDLE16 hnd)
4320 FIXME(mmsys,"(%04x): stub!\n", hnd);
4321 return FALSE;
4324 /**************************************************************************
4325 * mmThreadGetTask [MMSYSTEM.1125]
4327 LRESULT WINAPI mmThreadGetTask16(HANDLE16 hnd)
4329 FIXME(mmsys,"(%04x): stub!\n", hnd);
4330 return GetCurrentTask();
4333 /**************************************************************************
4334 * mmThreadIsValid [MMSYSTEM.1124]
4336 BOOL16 WINAPI mmThreadIsValid16(HANDLE16 handle)
4338 FIXME(mmsys, "(%04x): stub!\n", handle);
4339 return 0;
4342 /**************************************************************************
4343 * mmTaskCreate [MMSYSTEM.900]
4345 * Creates a 16 bit MM task. It's entry point is lpFunc, and it should be
4346 * called upon creation with dwPmt as parameter.
4348 HINSTANCE16 WINAPI mmTaskCreate16(SEGPTR lphnd, HINSTANCE16 *hMmTask, DWORD dwPmt)
4350 #if 1
4351 DWORD showCmd = 0x40002;
4352 LPSTR cmdline;
4353 WORD sel1, sel2;
4354 LOADPARAMS16 *lp;
4355 HINSTANCE16 ret, handle;
4357 TRACE(mmsys, "(%08lx,%p,%08lx);\n", lphnd, hMmTask, dwPmt);
4358 cmdline = (LPSTR)HeapAlloc(GetProcessHeap(), 0, 0x0d);
4359 cmdline[0] = 0x0d;
4360 (DWORD)cmdline[1] = (DWORD)lphnd;
4361 (DWORD)cmdline[5] = dwPmt;
4362 (DWORD)cmdline[9] = 0;
4364 sel1 = SELECTOR_AllocBlock(cmdline, 0x0d, SEGMENT_DATA, FALSE, FALSE);
4365 sel2 = SELECTOR_AllocBlock(&showCmd, sizeof(showCmd),
4366 SEGMENT_DATA, FALSE, FALSE);
4368 lp = (LOADPARAMS16 *)HeapAlloc(GetProcessHeap(), 0, sizeof(LOADPARAMS16));
4369 lp->hEnvironment = 0;
4370 lp->cmdLine = PTR_SEG_OFF_TO_SEGPTR(sel1, 0);
4371 lp->showCmd = PTR_SEG_OFF_TO_SEGPTR(sel2, 0);
4372 lp->reserved = 0;
4374 ret = LoadModule16("c:\\windows\\system\\mmtask.tsk", lp);
4375 TRACE(mmsys, "MMtask's handle = 0x%04x\n", ret);
4376 if (ret < 32) {
4377 if (ret)
4378 ret = 1;
4379 else
4380 ret = 2;
4381 handle = 0;
4382 } else {
4383 handle = ret;
4384 ret = 0;
4386 if (hMmTask)
4387 *hMmTask = handle;
4389 UnMapLS(PTR_SEG_OFF_TO_SEGPTR(sel2, 0));
4390 UnMapLS(PTR_SEG_OFF_TO_SEGPTR(sel1, 0));
4392 HeapFree(GetProcessHeap(), 0, lp);
4393 HeapFree(GetProcessHeap(), 0, cmdline);
4395 TRACE(mmsys, "=> 0x%04x/%d %04x\n", handle, ret, *(LPWORD)PTR_SEG_TO_LIN(lphnd));
4396 return ret;
4397 #else
4398 TRACE(mmsys, "(%p,%p,%08lx);\n", lphnd, hMmTask, x2);
4399 if (hMmTask)
4400 *hMmTask = 0xfade;
4401 return 0;
4402 #endif
4405 /**************************************************************************
4406 * mmTaskBlock [MMSYSTEM.902]
4408 void WINAPI mmTaskBlock16(HINSTANCE16 WINE_UNUSED hInst)
4410 MSG msg;
4412 do {
4413 GetMessageA(&msg, 0, 0, 0);
4414 if (msg.hwnd) {
4415 TranslateMessage(&msg);
4416 DispatchMessageA(&msg);
4418 } while (msg.message < 0x3A0);
4421 /**************************************************************************
4422 * mmTaskSignal [MMSYSTEM.903]
4424 LRESULT WINAPI mmTaskSignal16(HTASK16 ht)
4426 TRACE(mmsys,"(%04x);\n", ht);
4427 return PostAppMessageA(ht, WM_USER, 0, 0);
4430 /**************************************************************************
4431 * mmTaskYield16 [MMSYSTEM.905]
4433 void WINAPI mmTaskYield16(void)
4435 MSG msg;
4437 if (PeekMessageA(&msg, 0, 0, 0, 0)) {
4438 Yield16();
4442 /**************************************************************************
4443 * mmShowMMCPLPropertySheet [MMSYSTEM.1150]
4445 BOOL16 WINAPI mmShowMMCPLPropertySheet16(WORD w1, WORD w2, WORD w3, WORD w4, WORD w5, WORD w6, WORD w7)
4447 FIXME(mmsys, "%04x %04x %04x %04x %04x %04x %04x\n", w1, w2, w3, w4, w5, w6, w7);
4448 return TRUE;