ReactOS  0.4.15-dev-494-g1d8c567
mciwave.c
Go to the documentation of this file.
1 /*
2  * Wine Driver for MCI wave forms
3  *
4  * Copyright 1994 Martin Ayotte
5  * 1999,2000,2005 Eric Pouech
6  * 2000 Francois Jacques
7  * 2009 Jörg Höhle
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <assert.h>
25 #include <stdarg.h>
26 
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "mmddk.h"
32 #include "wownt32.h"
33 #include "digitalv.h"
34 #include "wine/debug.h"
35 
37 
38 typedef struct {
41  int nUseCount; /* Incremented for each shared open */
42  HMMIO hFile; /* mmio file handle open as Element */
43  MCIDEVICEID wNotifyDeviceID; /* MCI device ID with a pending notification */
44  HANDLE hCallback; /* Callback handle for pending notification */
45  LPWSTR lpFileName; /* Name of file (if any) */
47  LPWAVEFORMATEX lpWaveFormat; /* Points to wfxRef until set by OPEN or RECORD */
48  BOOL fInput; /* FALSE = Output, TRUE = Input */
49  WORD wInput; /* wave input device */
50  WORD wOutput; /* wave output device */
51  volatile WORD dwStatus; /* one from MCI_MODE_xxxx */
52  DWORD dwMciTimeFormat;/* One of the supported MCI_FORMAT_xxxx */
53  DWORD dwPosition; /* position in bytes in chunk */
54  HANDLE hEvent; /* for synchronization */
55  LONG dwEventCount; /* for synchronization */
56  MMCKINFO ckMainRIFF; /* main RIFF chunk */
57  MMCKINFO ckWaveData; /* data chunk */
58 } WINE_MCIWAVE;
59 
60 /* ===================================================================
61  * ===================================================================
62  * FIXME: should be using the new mmThreadXXXX functions from WINMM
63  * instead of those
64  * it would require to add a wine internal flag to mmThreadCreate
65  * in order to pass a 32 bit function instead of a 16 bit one
66  * ===================================================================
67  * =================================================================== */
68 
70 
71 struct SCA {
77 };
78 
79 /**************************************************************************
80  * MCI_SCAStarter [internal]
81  */
83 {
84  struct SCA* sca = (struct SCA*)arg;
85  DWORD ret;
86 
87  TRACE("In thread before async command (%08x,%08lx,%08lx)\n",
88  sca->wDevID, sca->dwParam1, sca->dwParam2);
89  ret = sca->cmd(sca->wDevID, sca->dwParam1 | MCI_WAIT, sca->dwParam2, sca->evt);
90  TRACE("In thread after async command (%08x,%08lx,%08lx)\n",
91  sca->wDevID, sca->dwParam1, sca->dwParam2);
92  HeapFree(GetProcessHeap(), 0, sca);
93  return ret;
94 }
95 
96 /**************************************************************************
97  * MCI_SendCommandAsync [internal]
98  */
101 {
102  HANDLE handles[2];
103  struct SCA* sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA) + size);
104 
105  if (sca == 0)
106  return MCIERR_OUT_OF_MEMORY;
107 
108  sca->wDevID = wDevID;
109  sca->cmd = cmd;
110  sca->dwParam1 = dwParam1;
111 
112  if (size && dwParam2) {
113  sca->dwParam2 = (DWORD_PTR)sca + sizeof(struct SCA);
114  /* copy structure passed by program in dwParam2 to be sure
115  * we can still use it whatever the program does
116  */
118  } else {
119  sca->dwParam2 = dwParam2;
120  }
121 
122  if ((sca->evt = handles[1] = CreateEventW(NULL, FALSE, FALSE, NULL)) == NULL ||
123  (handles[0] = CreateThread(NULL, 0, MCI_SCAStarter, sca, 0, NULL)) == 0) {
124  WARN("Couldn't allocate thread for async command handling, sending synchronously\n");
125  if (handles[1]) CloseHandle(handles[1]);
126  sca->evt = NULL;
127  return MCI_SCAStarter(&sca);
128  }
129 
131  /* wait until either:
132  * - the thread has finished (handles[0], likely an error)
133  * - init phase of async command is done (handles[1])
134  */
136  CloseHandle(handles[0]);
137  CloseHandle(handles[1]);
138  return 0;
139 }
140 
141 /*======================================================================*
142  * MCI WAVE implementation *
143  *======================================================================*/
144 
146 
147 /**************************************************************************
148  * MCIWAVE_drvOpen [internal]
149  */
151 {
152  WINE_MCIWAVE* wmw;
153 
154  if (modp == NULL) return 0xFFFFFFFF;
155 
157 
158  if (!wmw)
159  return 0;
160 
161  wmw->wDevID = modp->wDeviceID;
162  mciSetDriverData(wmw->wDevID, (DWORD_PTR)wmw);
165 
166  wmw->wfxRef.wFormatTag = WAVE_FORMAT_PCM;
167  wmw->wfxRef.nChannels = 1; /* MONO */
168  wmw->wfxRef.nSamplesPerSec = 11025;
169  wmw->wfxRef.nAvgBytesPerSec = 11025;
170  wmw->wfxRef.nBlockAlign = 1;
171  wmw->wfxRef.wBitsPerSample = 8;
172  wmw->wfxRef.cbSize = 0; /* don't care */
173 
174  return modp->wDeviceID;
175 }
176 
177 /**************************************************************************
178  * MCIWAVE_drvClose [internal]
179  */
181 {
182  WINE_MCIWAVE* wmw = (WINE_MCIWAVE*)mciGetDriverData(dwDevID);
183 
184  if (wmw) {
185  HeapFree(GetProcessHeap(), 0, wmw);
186  mciSetDriverData(dwDevID, 0);
187  return 1;
188  }
189  return (dwDevID == 0xFFFFFFFF) ? 1 : 0;
190 }
191 
192 /**************************************************************************
193  * WAVE_mciGetOpenDev [internal]
194  */
196 {
198 
199  if (wmw == NULL || wmw->nUseCount == 0) {
200  WARN("Invalid wDevID=%u\n", wDevID);
201  return 0;
202  }
203  return wmw;
204 }
205 
206 /**************************************************************************
207  * WAVE_mciNotify [internal]
208  *
209  * Notifications in MCI work like a 1-element queue.
210  * Each new notification request supersedes the previous one.
211  * This affects Play and Record; other commands are immediate.
212  */
213 static void WAVE_mciNotify(DWORD_PTR hWndCallBack, WINE_MCIWAVE* wmw, UINT wStatus)
214 {
215  /* We simply save one parameter by not passing the wDevID local
216  * to the command. They are the same (via mciGetDriverData).
217  */
221  mciDriverNotify(HWND_32(LOWORD(hWndCallBack)), wDevID, wStatus);
222 }
223 
224 /**************************************************************************
225  * WAVE_ConvertByteToTimeFormat [internal]
226  */
228 {
229  DWORD ret = 0;
230 
231  switch (wmw->dwMciTimeFormat) {
233  ret = MulDiv(val,1000,wmw->lpWaveFormat->nAvgBytesPerSec);
234  break;
235  case MCI_FORMAT_BYTES:
236  ret = val;
237  break;
238  case MCI_FORMAT_SAMPLES:
240  break;
241  default:
242  WARN("Bad time format %u!\n", wmw->dwMciTimeFormat);
243  }
244  TRACE("val=%u=0x%08x [tf=%u] => ret=%u\n", val, val, wmw->dwMciTimeFormat, ret);
245  return ret;
246 }
247 
248 /**************************************************************************
249  * WAVE_ConvertTimeFormatToByte [internal]
250  */
252 {
253  DWORD ret = 0;
254 
255  switch (wmw->dwMciTimeFormat) {
257  ret = MulDiv(val,wmw->lpWaveFormat->nAvgBytesPerSec,1000);
258  if (ret > wmw->ckWaveData.cksize &&
260  ret = wmw->ckWaveData.cksize;
261  break;
262  case MCI_FORMAT_BYTES:
263  ret = val;
264  break;
265  case MCI_FORMAT_SAMPLES:
267  break;
268  default:
269  WARN("Bad time format %u!\n", wmw->dwMciTimeFormat);
270  }
271  TRACE("val=%u=0x%08x [tf=%u] => ret=%u\n", val, val, wmw->dwMciTimeFormat, ret);
272  return ret;
273 }
274 
275 /**************************************************************************
276  * WAVE_mciReadFmt [internal]
277  */
278 static DWORD WAVE_mciReadFmt(WINE_MCIWAVE* wmw, const MMCKINFO* pckMainRIFF)
279 {
280  MMCKINFO mmckInfo;
281  LONG r;
282  LPWAVEFORMATEX pwfx;
283 
284  mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
285  if (mmioDescend(wmw->hFile, &mmckInfo, pckMainRIFF, MMIO_FINDCHUNK) != 0)
286  return MCIERR_INVALID_FILE;
287  TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08X\n",
288  (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType, mmckInfo.cksize);
289 
290  pwfx = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
291  if (!pwfx) return MCIERR_OUT_OF_MEMORY;
292 
293  r = mmioRead(wmw->hFile, (HPSTR)pwfx, mmckInfo.cksize);
294  if (r < sizeof(PCMWAVEFORMAT)) {
295  HeapFree(GetProcessHeap(), 0, pwfx);
296  return MCIERR_INVALID_FILE;
297  }
298  TRACE("wFormatTag=%04X !\n", pwfx->wFormatTag);
299  TRACE("nChannels=%d\n", pwfx->nChannels);
300  TRACE("nSamplesPerSec=%d\n", pwfx->nSamplesPerSec);
301  TRACE("nAvgBytesPerSec=%d\n", pwfx->nAvgBytesPerSec);
302  TRACE("nBlockAlign=%d\n", pwfx->nBlockAlign);
303  TRACE("wBitsPerSample=%u !\n", pwfx->wBitsPerSample);
304  if (r >= sizeof(WAVEFORMATEX))
305  TRACE("cbSize=%u !\n", pwfx->cbSize);
306  if ((pwfx->wFormatTag != WAVE_FORMAT_PCM)
307  && (r < sizeof(WAVEFORMATEX) || (r < sizeof(WAVEFORMATEX) + pwfx->cbSize))) {
308  HeapFree(GetProcessHeap(), 0, pwfx);
309  return MCIERR_INVALID_FILE;
310  }
311  wmw->lpWaveFormat = pwfx;
312 
313  mmioAscend(wmw->hFile, &mmckInfo, 0);
314  wmw->ckWaveData.ckid = mmioFOURCC('d', 'a', 't', 'a');
315  if (mmioDescend(wmw->hFile, &wmw->ckWaveData, pckMainRIFF, MMIO_FINDCHUNK) != 0) {
316  TRACE("can't find data chunk\n");
317  return MCIERR_INVALID_FILE;
318  }
319  TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08X\n",
321  return 0;
322 }
323 
324 /**************************************************************************
325  * WAVE_mciDefaultFmt [internal]
326  *
327  * wmw->lpWaveFormat points to the default wave format at wmw->wfxRef
328  * until either Open File or Record. It becomes immutable afterwards,
329  * i.e. Set wave format or channels etc. is subsequently refused.
330  */
332 {
333  wmw->lpWaveFormat = &wmw->wfxRef;
335  wmw->lpWaveFormat->nChannels = 1;
336  wmw->lpWaveFormat->nSamplesPerSec = 11025;
337  wmw->lpWaveFormat->nAvgBytesPerSec = 11025;
338  wmw->lpWaveFormat->nBlockAlign = 1;
339  wmw->lpWaveFormat->wBitsPerSample = 8;
340  wmw->lpWaveFormat->cbSize = 0;
341 }
342 
343 /**************************************************************************
344  * WAVE_mciCreateRIFFSkeleton [internal]
345  */
347 {
348  MMCKINFO ckWaveFormat;
349  LPMMCKINFO lpckRIFF = &(wmw->ckMainRIFF);
350  LPMMCKINFO lpckWaveData = &(wmw->ckWaveData);
351 
352  lpckRIFF->ckid = FOURCC_RIFF;
353  lpckRIFF->fccType = mmioFOURCC('W', 'A', 'V', 'E');
354  lpckRIFF->cksize = 0;
355 
356  if (MMSYSERR_NOERROR != mmioCreateChunk(wmw->hFile, lpckRIFF, MMIO_CREATERIFF))
357  goto err;
358 
359  ckWaveFormat.fccType = 0;
360  ckWaveFormat.ckid = mmioFOURCC('f', 'm', 't', ' ');
361  ckWaveFormat.cksize = sizeof(PCMWAVEFORMAT);
362 
363  /* Set wave format accepts PCM only, however open an
364  * existing ADPCM file, record into it and the MCI will
365  * happily save back in that format. */
366  if (wmw->lpWaveFormat->wFormatTag == WAVE_FORMAT_PCM) {
367  if (wmw->lpWaveFormat->nBlockAlign !=
369  WORD size = wmw->lpWaveFormat->nChannels *
371  WARN("Incorrect nBlockAlign (%d), setting it to %d\n",
372  wmw->lpWaveFormat->nBlockAlign, size);
373  wmw->lpWaveFormat->nBlockAlign = size;
374  }
375  if (wmw->lpWaveFormat->nAvgBytesPerSec !=
377  DWORD speed = wmw->lpWaveFormat->nSamplesPerSec *
379  WARN("Incorrect nAvgBytesPerSec (%d), setting it to %d\n",
380  wmw->lpWaveFormat->nAvgBytesPerSec, speed);
381  wmw->lpWaveFormat->nAvgBytesPerSec = speed;
382  }
383  }
384  if (wmw->lpWaveFormat == &wmw->wfxRef) {
386  if (!pwfx) return MCIERR_OUT_OF_MEMORY;
387  /* Set wave format accepts PCM only so the size is known. */
389  *pwfx = wmw->wfxRef;
390  wmw->lpWaveFormat = pwfx;
391  }
392 
393  if (MMSYSERR_NOERROR != mmioCreateChunk(wmw->hFile, &ckWaveFormat, 0))
394  goto err;
395 
396  if (-1 == mmioWrite(wmw->hFile, (HPCSTR)wmw->lpWaveFormat, (WAVE_FORMAT_PCM==wmw->lpWaveFormat->wFormatTag)
397  ? sizeof(PCMWAVEFORMAT) : sizeof(WAVEFORMATEX)+wmw->lpWaveFormat->cbSize))
398  goto err;
399 
400  if (MMSYSERR_NOERROR != mmioAscend(wmw->hFile, &ckWaveFormat, 0))
401  goto err;
402 
403  lpckWaveData->cksize = 0;
404  lpckWaveData->fccType = 0;
405  lpckWaveData->ckid = mmioFOURCC('d', 'a', 't', 'a');
406 
407  /* create data chunk */
408  if (MMSYSERR_NOERROR != mmioCreateChunk(wmw->hFile, lpckWaveData, 0))
409  goto err;
410 
411  return 0;
412 
413 err:
414  /* mciClose takes care of wmw->lpWaveFormat. */
415  return MCIERR_INVALID_FILE;
416 }
417 
418 static DWORD create_tmp_file(HMMIO* hFile, LPWSTR* pszTmpFileName)
419 {
420  WCHAR szTmpPath[MAX_PATH];
421  WCHAR szPrefix[4];
422  DWORD dwRet = MMSYSERR_NOERROR;
423 
424  szPrefix[0] = 'M';
425  szPrefix[1] = 'C';
426  szPrefix[2] = 'I';
427  szPrefix[3] = '\0';
428 
429  if (!GetTempPathW(ARRAY_SIZE(szTmpPath), szTmpPath)) {
430  WARN("can't retrieve temp path!\n");
431  *pszTmpFileName = NULL;
432  return MCIERR_FILE_NOT_FOUND;
433  }
434 
435  *pszTmpFileName = HeapAlloc(GetProcessHeap(),
437  MAX_PATH * sizeof(WCHAR));
438  if (!GetTempFileNameW(szTmpPath, szPrefix, 0, *pszTmpFileName)) {
439  WARN("can't retrieve temp file name!\n");
440  HeapFree(GetProcessHeap(), 0, *pszTmpFileName);
441  return MCIERR_FILE_NOT_FOUND;
442  }
443 
444  TRACE("%s!\n", debugstr_w(*pszTmpFileName));
445 
446  if (*pszTmpFileName && (*pszTmpFileName)[0]) {
447 
448  *hFile = mmioOpenW(*pszTmpFileName, NULL,
450 
451  if (*hFile == 0) {
452  WARN("can't create file=%s!\n", debugstr_w(*pszTmpFileName));
453  /* temporary file could not be created. clean filename. */
454  HeapFree(GetProcessHeap(), 0, *pszTmpFileName);
455  dwRet = MCIERR_FILE_NOT_FOUND;
456  }
457  }
458  return dwRet;
459 }
460 
462 {
463  LRESULT dwRet = MMSYSERR_NOERROR;
464  LPWSTR fn;
465 
466  fn = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1) * sizeof(WCHAR));
467  if (!fn) return MCIERR_OUT_OF_MEMORY;
468  lstrcpyW(fn, filename);
469  HeapFree(GetProcessHeap(), 0, wmw->lpFileName);
470  wmw->lpFileName = fn;
471 
472  if (filename[0]) {
473  /* FIXME : what should be done if wmw->hFile is already != 0, or the driver is playin' */
474  TRACE("MCI_OPEN_ELEMENT %s!\n", debugstr_w(filename));
475 
478 
479  if (wmw->hFile == 0) {
480  WARN("can't find file=%s!\n", debugstr_w(filename));
481  dwRet = MCIERR_FILE_NOT_FOUND;
482  }
483  else
484  {
485  LPMMCKINFO lpckMainRIFF = &wmw->ckMainRIFF;
486 
487  /* make sure we're at the beginning of the file */
488  mmioSeek(wmw->hFile, 0, SEEK_SET);
489 
490  /* first reading of this file. read the waveformat chunk */
491  if (mmioDescend(wmw->hFile, lpckMainRIFF, NULL, 0) != 0) {
492  dwRet = MCIERR_INVALID_FILE;
493  } else {
494  TRACE("ParentChunk ckid=%.4s fccType=%.4s cksize=%08X\n",
495  (LPSTR)&(lpckMainRIFF->ckid),
496  (LPSTR) &(lpckMainRIFF->fccType),
497  (lpckMainRIFF->cksize));
498 
499  if ((lpckMainRIFF->ckid != FOURCC_RIFF) ||
500  lpckMainRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E')) {
501  dwRet = MCIERR_INVALID_FILE;
502  } else {
503  dwRet = WAVE_mciReadFmt(wmw, lpckMainRIFF);
504  }
505  }
506  }
507  }
508  return dwRet;
509 }
510 
511 /**************************************************************************
512  * WAVE_mciOpen [internal]
513  */
515 {
516  DWORD dwRet = 0;
518 
519  TRACE("(%04X, %08X, %p)\n", wDevID, dwFlags, lpOpenParms);
520  if (lpOpenParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
521  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
522 
525 
526  if (wmw->nUseCount > 0) {
527  /* The driver is already opened on this channel
528  * Wave driver cannot be shared
529  */
530  return MCIERR_DEVICE_OPEN;
531  }
532 
533  wmw->nUseCount++;
534 
535  wmw->wInput = wmw->wOutput = WAVE_MAPPER;
536  wmw->fInput = FALSE;
537  wmw->hWave = 0;
539  wmw->hFile = 0;
540  wmw->lpFileName = NULL; /* will be set by WAVE_mciOpenFile */
541  wmw->hCallback = NULL;
542  WAVE_mciDefaultFmt(wmw);
543 
544  TRACE("wDevID=%04X (lpParams->wDeviceID=%08X)\n", wDevID, lpOpenParms->wDeviceID);
545  /* Logs show the native winmm calls us with 0 still in lpOpenParms.wDeviceID */
546  wmw->wNotifyDeviceID = wDevID;
547 
548  if (dwFlags & MCI_OPEN_ELEMENT) {
550  /* could it be that (DWORD)lpOpenParms->lpstrElementName
551  * contains the hFile value ?
552  */
554  } else {
555  dwRet = WAVE_mciOpenFile(wmw, lpOpenParms->lpstrElementName);
556  }
557  }
558  TRACE("hFile=%p\n", wmw->hFile);
559 
560  if (dwRet == 0) {
561  wmw->dwPosition = 0;
562 
563  wmw->dwStatus = MCI_MODE_STOP;
564 
565  if (dwFlags & MCI_NOTIFY)
566  WAVE_mciNotify(lpOpenParms->dwCallback, wmw, MCI_NOTIFY_SUCCESSFUL);
567  } else {
568  wmw->nUseCount--;
569  if (wmw->hFile != 0)
570  mmioClose(wmw->hFile, 0);
571  wmw->hFile = 0;
572  HeapFree(GetProcessHeap(), 0, wmw->lpFileName);
573  wmw->lpFileName = NULL;
574  }
575  return dwRet;
576 }
577 
578 /**************************************************************************
579  * WAVE_mciCue [internal]
580  */
582 {
584 
585  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
586 
587  /* Tests on systems without sound drivers show that Cue, like
588  * Record and Play, opens winmm, returning MCIERR_WAVE_xyPUTSUNSUITABLE.
589  * The first Cue Notify does not immediately return the
590  * notification, as if a player or recorder thread is started.
591  * PAUSE mode is reported when successful, but this mode is
592  * different from the normal Pause, because a) Pause then returns
593  * NONAPPLICABLE_FUNCTION instead of 0 and b) Set Channels etc. is
594  * still accepted, returning the original notification as ABORTED.
595  * I.e. Cue allows subsequent format changes, unlike Record or
596  * Open file, closes winmm if the format changes and stops this
597  * thread.
598  * Wine creates one player or recorder thread per async. Play or
599  * Record command. Notification behaviour suggests that MS-W*
600  * reuses a single thread to improve response times. Having Cue
601  * start this thread early helps to improve Play/Record's initial
602  * response time. In effect, Cue is a performance hint, which
603  * justifies our almost no-op implementation.
604  */
605 
606  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
608 
609  if ((dwFlags & MCI_NOTIFY) && lpParms)
611 
612  return MMSYSERR_NOERROR;
613 }
614 
615 /**************************************************************************
616  * WAVE_mciStop [internal]
617  */
619 {
620  DWORD dwRet = 0;
622 
623  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
624 
625  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
626 
627  if (wmw->dwStatus != MCI_MODE_STOP) {
629  if (old) mciDriverNotify(old, wDevID, MCI_NOTIFY_ABORTED);
630  }
631 
632  /* wait for playback thread (if any) to exit before processing further */
633  switch (wmw->dwStatus) {
634  case MCI_MODE_PAUSE:
635  case MCI_MODE_PLAY:
636  case MCI_MODE_RECORD:
637  {
638  int oldStat = wmw->dwStatus;
640  if (oldStat == MCI_MODE_PAUSE)
641  dwRet = (wmw->fInput) ? waveInReset(wmw->hWave) : waveOutReset(wmw->hWave);
642  }
643  while (wmw->dwStatus != MCI_MODE_STOP)
644  Sleep(10);
645  break;
646  }
647 
648  /* sanity resets */
649  wmw->dwStatus = MCI_MODE_STOP;
650 
651  if ((dwFlags & MCI_NOTIFY) && lpParms && MMSYSERR_NOERROR==dwRet)
653 
654  return dwRet;
655 }
656 
657 /**************************************************************************
658  * WAVE_mciClose [internal]
659  */
661 {
662  DWORD dwRet = 0;
664 
665  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
666 
667  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
668 
669  if (wmw->dwStatus != MCI_MODE_STOP) {
670  /* mciStop handles MCI_NOTIFY_ABORTED */
671  dwRet = WAVE_mciStop(wDevID, MCI_WAIT, lpParms);
672  }
673 
674  wmw->nUseCount--;
675 
676  if (wmw->nUseCount == 0) {
677  if (wmw->hFile != 0) {
678  mmioClose(wmw->hFile, 0);
679  wmw->hFile = 0;
680  }
681  }
682 
683  if (wmw->lpWaveFormat != &wmw->wfxRef)
685  wmw->lpWaveFormat = &wmw->wfxRef;
686  HeapFree(GetProcessHeap(), 0, wmw->lpFileName);
687  wmw->lpFileName = NULL;
688 
689  if ((dwFlags & MCI_NOTIFY) && lpParms) {
690  WAVE_mciNotify(lpParms->dwCallback, wmw,
691  (dwRet == 0) ? MCI_NOTIFY_SUCCESSFUL : MCI_NOTIFY_FAILURE);
692  }
693 
694  return 0;
695 }
696 
697 /**************************************************************************
698  * WAVE_mciPlayCallback [internal]
699  */
700 static void CALLBACK WAVE_mciPlayCallback(HWAVEOUT hwo, UINT uMsg,
701  DWORD_PTR dwInstance,
703 {
704  WINE_MCIWAVE* wmw = (WINE_MCIWAVE*)dwInstance;
705 
706  switch (uMsg) {
707  case WOM_OPEN:
708  case WOM_CLOSE:
709  break;
710  case WOM_DONE:
712  TRACE("Returning waveHdr=%lx\n", dwParam1);
713  SetEvent(wmw->hEvent);
714  break;
715  default:
716  ERR("Unknown uMsg=%d\n", uMsg);
717  }
718 }
719 
720 /******************************************************************
721  * WAVE_mciPlayWaitDone [internal]
722  */
724 {
725  for (;;) {
726  ResetEvent(wmw->hEvent);
727  if (InterlockedDecrement(&wmw->dwEventCount) >= 0) {
728  break;
729  }
731 
733  }
734 }
735 
736 /**************************************************************************
737  * WAVE_mciPlay [internal]
738  */
740 {
741  LPMCI_PLAY_PARMS lpParms = (void*)pmt;
742  DWORD end;
744  DWORD dwRet;
745  LPWAVEHDR waveHdr = NULL;
747  HANDLE oldcb;
748  int whidx;
749 
750  TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
751 
752  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
753  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
754 
755  if (wmw->hFile == 0) {
756  WARN("Can't play: no file=%s!\n", debugstr_w(wmw->lpFileName));
757  return MCIERR_FILE_NOT_FOUND;
758  }
759 
760  if (wmw->dwStatus == MCI_MODE_PAUSE && !wmw->fInput && !(dwFlags & (MCI_FROM | MCI_TO))) {
761  /* FIXME: notification is different with Resume than Play */
763  }
764 
769  if ( !(wmw->dwStatus == MCI_MODE_STOP) &&
770  !((wmw->dwStatus == MCI_MODE_PLAY) && (dwFlags & MCI_WAIT) && !wmw->hWave)) {
771  /* FIXME: Check FROM/TO parameters first. */
772  /* FIXME: Play; Play [notify|wait] must hook into the running player. */
773  dwRet = WAVE_mciStop(wDevID, MCI_WAIT, NULL);
774  if (dwRet) return dwRet;
775  }
776 
777  if (wmw->lpWaveFormat->wFormatTag == WAVE_FORMAT_PCM) {
778  if (wmw->lpWaveFormat->nBlockAlign !=
780  WARN("Incorrect nBlockAlign (%d), setting it to %d\n",
782  wmw->lpWaveFormat->nChannels *
783  wmw->lpWaveFormat->wBitsPerSample/8);
784  wmw->lpWaveFormat->nBlockAlign =
785  wmw->lpWaveFormat->nChannels *
787  }
788  if (wmw->lpWaveFormat->nAvgBytesPerSec !=
790  WARN("Incorrect nAvgBytesPerSec (%d), setting it to %d\n",
793  wmw->lpWaveFormat->nBlockAlign);
797  }
798  }
799 
800  end = wmw->ckWaveData.cksize;
801  if (dwFlags & MCI_TO) {
802  DWORD position = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwTo);
803  if (position > end) return MCIERR_OUTOFRANGE;
804  end = position;
805  }
806  if (dwFlags & MCI_FROM) {
807  DWORD position = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwFrom);
808  if (position > end) return MCIERR_OUTOFRANGE;
809  /* Seek rounds down, so do we. */
810  position /= wmw->lpWaveFormat->nBlockAlign;
811  position *= wmw->lpWaveFormat->nBlockAlign;
812  wmw->dwPosition = position;
813  }
814  if (end < wmw->dwPosition) return MCIERR_OUTOFRANGE;
815  left = end - wmw->dwPosition;
816  if (0==left) return MMSYSERR_NOERROR; /* FIXME: NOTIFY */
817 
818  wmw->fInput = FALSE; /* FIXME: waveInOpen may have been called. */
819  wmw->dwStatus = MCI_MODE_PLAY;
820 
821  if (!(dwFlags & MCI_WAIT)) {
823  (DWORD_PTR)lpParms, sizeof(MCI_PLAY_PARMS));
824  }
825 
826  TRACE("Playing from byte=%u to byte=%u\n", wmw->dwPosition, end);
827 
829  (dwFlags & MCI_NOTIFY) ? HWND_32(LOWORD(lpParms->dwCallback)) : NULL);
830  if (oldcb) mciDriverNotify(oldcb, wDevID, MCI_NOTIFY_ABORTED);
831  oldcb = NULL;
832 
833 #define WAVE_ALIGN_ON_BLOCK(wmw,v) \
834 ((((v) + (wmw)->lpWaveFormat->nBlockAlign - 1) / (wmw)->lpWaveFormat->nBlockAlign) * (wmw)->lpWaveFormat->nBlockAlign)
835 
836  /* go back to beginning of chunk plus the requested position */
837  /* FIXME: I'm not sure this is correct, notably because some data linked to
838  * the decompression state machine will not be correctly initialized.
839  * try it this way (other way would be to decompress from 0 up to dwPosition
840  * and to start sending to hWave when dwPosition is reached)
841  */
842  mmioSeek(wmw->hFile, wmw->ckWaveData.dwDataOffset + wmw->dwPosition, SEEK_SET); /* >= 0 */
843 
844  dwRet = waveOutOpen((HWAVEOUT *)&wmw->hWave, wmw->wOutput, wmw->lpWaveFormat,
846 
847  if (dwRet != 0) {
848  TRACE("Can't open low level audio device %d\n", dwRet);
849  dwRet = MCIERR_DEVICE_OPEN;
850  wmw->hWave = 0;
851  goto cleanUp;
852  }
853 
854  /* make it so that 3 buffers per second are needed */
855  bufsize = WAVE_ALIGN_ON_BLOCK(wmw, wmw->lpWaveFormat->nAvgBytesPerSec / 3);
856 
857  waveHdr = HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WAVEHDR) + 2 * bufsize);
858  waveHdr[0].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR);
859  waveHdr[1].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR) + bufsize;
860  waveHdr[0].dwUser = waveHdr[1].dwUser = 0L;
861  waveHdr[0].dwLoops = waveHdr[1].dwLoops = 0L;
862  waveHdr[0].dwFlags = waveHdr[1].dwFlags = 0L;
863  waveHdr[0].dwBufferLength = waveHdr[1].dwBufferLength = bufsize;
864  if (waveOutPrepareHeader(wmw->hWave, &waveHdr[0], sizeof(WAVEHDR)) ||
865  waveOutPrepareHeader(wmw->hWave, &waveHdr[1], sizeof(WAVEHDR))) {
866  dwRet = MCIERR_INTERNAL;
867  goto cleanUp;
868  }
869 
870  whidx = 0;
871  wmw->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
872  if (!wmw->hEvent) {
873  dwRet = MCIERR_OUT_OF_MEMORY;
874  goto cleanUp;
875  }
876  wmw->dwEventCount = 1L; /* for first buffer */
877 
878  TRACE("Playing (normalized) from byte=%u for %u bytes\n", wmw->dwPosition, left);
879  if (hEvent) SetEvent(hEvent);
880 
881  /* FIXME: this doesn't work if wmw->dwPosition != 0 */
882  while (left > 0 && wmw->dwStatus != MCI_MODE_STOP && wmw->dwStatus != MCI_MODE_NOT_READY) {
883  count = mmioRead(wmw->hFile, waveHdr[whidx].lpData, min(bufsize, left));
884  TRACE("mmioRead bufsize=%d count=%d\n", bufsize, count);
885  if (count < 1)
886  break;
887  /* count is always <= bufsize, so this is correct regarding the
888  * waveOutPrepareHeader function
889  */
890  waveHdr[whidx].dwBufferLength = count;
891  waveHdr[whidx].dwFlags &= ~WHDR_DONE;
892  TRACE("before WODM_WRITE lpWaveHdr=%p dwBufferLength=%u\n",
893  &waveHdr[whidx], waveHdr[whidx].dwBufferLength);
894  dwRet = waveOutWrite(wmw->hWave, &waveHdr[whidx], sizeof(WAVEHDR));
895  if (dwRet) {
896  ERR("Aborting play loop, WODM_WRITE error %d\n", dwRet);
897  dwRet = MCIERR_HARDWARE;
898  break;
899  }
900  left -= count;
901  wmw->dwPosition += count;
902  TRACE("after WODM_WRITE dwPosition=%u\n", wmw->dwPosition);
903  /* InterlockedDecrement if and only if waveOutWrite is successful */
905  whidx ^= 1;
906  }
907 
908  WAVE_mciPlayWaitDone(wmw); /* to balance first buffer */
909 
910  /* just to get rid of some race conditions between play, stop and pause */
911  waveOutReset(wmw->hWave);
912 
913  waveOutUnprepareHeader(wmw->hWave, &waveHdr[0], sizeof(WAVEHDR));
914  waveOutUnprepareHeader(wmw->hWave, &waveHdr[1], sizeof(WAVEHDR));
915 
916 cleanUp:
917  if (dwFlags & MCI_NOTIFY)
918  oldcb = InterlockedExchangePointer(&wmw->hCallback, NULL);
919 
920  HeapFree(GetProcessHeap(), 0, waveHdr);
921 
922  if (wmw->hWave) {
923  waveOutClose(wmw->hWave);
924  wmw->hWave = 0;
925  }
926  CloseHandle(wmw->hEvent);
927  wmw->hEvent = NULL;
928 
929  wmw->dwStatus = MCI_MODE_STOP;
930 
931  /* Let the potentially asynchronous commands support FAILURE notification. */
932  if (oldcb) mciDriverNotify(oldcb, wDevID,
934 
935  return dwRet;
936 }
937 
938 /**************************************************************************
939  * WAVE_mciRecordCallback [internal]
940  */
941 static void CALLBACK WAVE_mciRecordCallback(HWAVEOUT hwo, UINT uMsg,
942  DWORD_PTR dwInstance,
944 {
945  WINE_MCIWAVE* wmw = (WINE_MCIWAVE*)dwInstance;
946  LPWAVEHDR lpWaveHdr;
947  LONG count = 0;
948 
949  switch (uMsg) {
950  case WIM_OPEN:
951  case WIM_CLOSE:
952  break;
953  case WIM_DATA:
954  lpWaveHdr = (LPWAVEHDR) dwParam1;
955 
957 
958  count = mmioWrite(wmw->hFile, lpWaveHdr->lpData, lpWaveHdr->dwBytesRecorded);
959 
960  lpWaveHdr->dwFlags &= ~WHDR_DONE;
961  if (count > 0)
962  wmw->dwPosition += count;
963  /* else error reporting ?? */
964  if (wmw->dwStatus == MCI_MODE_RECORD)
965  {
966  /* Only queue up another buffer if we are recording. We could receive this
967  message also when waveInReset() is called, since it notifies on all wave
968  buffers that are outstanding. Queueing up more sometimes causes waveInClose
969  to fail. */
970  waveInAddBuffer(wmw->hWave, lpWaveHdr, sizeof(*lpWaveHdr));
971  TRACE("after mmioWrite dwPosition=%u\n", wmw->dwPosition);
972  }
973 
974  SetEvent(wmw->hEvent);
975  break;
976  default:
977  ERR("Unknown uMsg=%d\n", uMsg);
978  }
979 }
980 
981 /******************************************************************
982  * WAVE_mciRecordWaitDone [internal]
983  */
985 {
986  for (;;) {
987  ResetEvent(wmw->hEvent);
988  if (InterlockedDecrement(&wmw->dwEventCount) >= 0) {
989  break;
990  }
992 
994  }
995 }
996 
997 /**************************************************************************
998  * WAVE_mciRecord [internal]
999  */
1001 {
1002  LPMCI_RECORD_PARMS lpParms = (void*)pmt;
1003  DWORD end;
1004  DWORD dwRet = MMSYSERR_NOERROR;
1005  LONG bufsize;
1006  LPWAVEHDR waveHdr = NULL;
1008  HANDLE oldcb;
1009 
1010  TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
1011 
1012  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1013  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1014 
1015  if (wmw->dwStatus == MCI_MODE_PAUSE && wmw->fInput) {
1016  /* FIXME: parameters (start/end) in lpParams may not be used */
1017  return WAVE_mciResume(wDevID, dwFlags, (LPMCI_GENERIC_PARMS)lpParms);
1018  }
1019 
1024  if ( !(wmw->dwStatus == MCI_MODE_STOP) &&
1025  !((wmw->dwStatus == MCI_MODE_RECORD) && (dwFlags & MCI_WAIT) && !wmw->hWave)) {
1026  return MCIERR_INTERNAL;
1027  }
1028 
1029  wmw->fInput = TRUE; /* FIXME: waveOutOpen may have been called. */
1030  wmw->dwStatus = MCI_MODE_RECORD;
1031 
1032  if (!(dwFlags & MCI_WAIT)) {
1034  (DWORD_PTR)lpParms, sizeof(MCI_RECORD_PARMS));
1035  }
1036 
1037  /* FIXME: we only re-create the RIFF structure from an existing file (if any)
1038  * we don't modify the wave part of an existing file (ie. we always erase an
1039  * existing content, we don't overwrite)
1040  */
1041  HeapFree(GetProcessHeap(), 0, wmw->lpFileName);
1042  dwRet = create_tmp_file(&wmw->hFile, (WCHAR**)&wmw->lpFileName);
1043  if (dwRet != 0) return dwRet;
1044 
1045  /* new RIFF file, lpWaveFormat now valid */
1046  dwRet = WAVE_mciCreateRIFFSkeleton(wmw);
1047  if (dwRet != 0) return dwRet;
1048 
1049  if (dwFlags & MCI_TO) {
1050  end = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwTo);
1051  } else end = 0xFFFFFFFF;
1052  if (dwFlags & MCI_FROM) {
1053  DWORD position = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwFrom);
1054  if (wmw->ckWaveData.cksize < position) return MCIERR_OUTOFRANGE;
1055  /* Seek rounds down, so do we. */
1056  position /= wmw->lpWaveFormat->nBlockAlign;
1057  position *= wmw->lpWaveFormat->nBlockAlign;
1058  wmw->dwPosition = position;
1059  }
1060  if (end==wmw->dwPosition) return MMSYSERR_NOERROR; /* FIXME: NOTIFY */
1061 
1062  TRACE("Recording from byte=%u to byte=%u\n", wmw->dwPosition, end);
1063 
1064  oldcb = InterlockedExchangePointer(&wmw->hCallback,
1065  (dwFlags & MCI_NOTIFY) ? HWND_32(LOWORD(lpParms->dwCallback)) : NULL);
1066  if (oldcb) mciDriverNotify(oldcb, wDevID, MCI_NOTIFY_ABORTED);
1067  oldcb = NULL;
1068 
1069 #define WAVE_ALIGN_ON_BLOCK(wmw,v) \
1070 ((((v) + (wmw)->lpWaveFormat->nBlockAlign - 1) / (wmw)->lpWaveFormat->nBlockAlign) * (wmw)->lpWaveFormat->nBlockAlign)
1071 
1073 
1074  /* Go back to the beginning of the chunk plus the requested position */
1075  /* FIXME: I'm not sure this is correct, notably because some data linked to
1076  * the decompression state machine will not be correctly initialized.
1077  * Try it this way (other way would be to decompress from 0 up to dwPosition
1078  * and to start sending to hWave when dwPosition is reached).
1079  */
1080  mmioSeek(wmw->hFile, wmw->ckWaveData.dwDataOffset + wmw->dwPosition, SEEK_SET); /* >= 0 */
1081 
1082  dwRet = waveInOpen((HWAVEIN*)&wmw->hWave, wmw->wInput, wmw->lpWaveFormat,
1084 
1085  if (dwRet != MMSYSERR_NOERROR) {
1086  TRACE("Can't open low level audio device %d\n", dwRet);
1087  dwRet = MCIERR_DEVICE_OPEN;
1088  wmw->hWave = 0;
1089  goto cleanUp;
1090  }
1091 
1092  /* make it so that 3 buffers per second are needed */
1093  bufsize = WAVE_ALIGN_ON_BLOCK(wmw, wmw->lpWaveFormat->nAvgBytesPerSec / 3);
1094 
1095  waveHdr = HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WAVEHDR) + 2 * bufsize);
1096  waveHdr[0].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR);
1097  waveHdr[1].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR) + bufsize;
1098  waveHdr[0].dwUser = waveHdr[1].dwUser = 0L;
1099  waveHdr[0].dwLoops = waveHdr[1].dwLoops = 0L;
1100  waveHdr[0].dwFlags = waveHdr[1].dwFlags = 0L;
1101  waveHdr[0].dwBufferLength = waveHdr[1].dwBufferLength = bufsize;
1102 
1103  if (waveInPrepareHeader(wmw->hWave, &waveHdr[0], sizeof(WAVEHDR)) ||
1104  waveInPrepareHeader(wmw->hWave, &waveHdr[1], sizeof(WAVEHDR))) {
1105  dwRet = MCIERR_INTERNAL;
1106  goto cleanUp;
1107  }
1108 
1109  if (waveInAddBuffer(wmw->hWave, &waveHdr[0], sizeof(WAVEHDR)) ||
1110  waveInAddBuffer(wmw->hWave, &waveHdr[1], sizeof(WAVEHDR))) {
1111  dwRet = MCIERR_INTERNAL;
1112  goto cleanUp;
1113  }
1114 
1115  wmw->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
1116  wmw->dwEventCount = 1L; /* for first buffer */
1117 
1118  TRACE("Recording (normalized) from byte=%u for %u bytes\n", wmw->dwPosition, end - wmw->dwPosition);
1119 
1120  waveInStart(wmw->hWave);
1121 
1122  if (hEvent) SetEvent(hEvent);
1123 
1124  while (wmw->dwPosition < end && wmw->dwStatus != MCI_MODE_STOP && wmw->dwStatus != MCI_MODE_NOT_READY) {
1126  }
1127  /* Grab callback before another thread kicks in after we change dwStatus. */
1128  if (dwFlags & MCI_NOTIFY) {
1129  oldcb = InterlockedExchangePointer(&wmw->hCallback, NULL);
1130  dwFlags &= ~MCI_NOTIFY;
1131  }
1132  /* needed so that the callback above won't add again the buffers returned by the reset */
1133  wmw->dwStatus = MCI_MODE_STOP;
1134 
1135  waveInReset(wmw->hWave);
1136 
1137  waveInUnprepareHeader(wmw->hWave, &waveHdr[0], sizeof(WAVEHDR));
1138  waveInUnprepareHeader(wmw->hWave, &waveHdr[1], sizeof(WAVEHDR));
1139 
1140  dwRet = 0;
1141 
1142 cleanUp:
1143  if (dwFlags & MCI_NOTIFY)
1144  oldcb = InterlockedExchangePointer(&wmw->hCallback, NULL);
1145 
1146  HeapFree(GetProcessHeap(), 0, waveHdr);
1147 
1148  if (wmw->hWave) {
1149  waveInClose(wmw->hWave);
1150  wmw->hWave = 0;
1151  }
1152  CloseHandle(wmw->hEvent);
1153 
1154  wmw->dwStatus = MCI_MODE_STOP;
1155 
1156  if (oldcb) mciDriverNotify(oldcb, wDevID,
1158 
1159  return dwRet;
1160 
1161 }
1162 
1163 /**************************************************************************
1164  * WAVE_mciPause [internal]
1165  */
1167 {
1168  DWORD dwRet;
1170 
1171  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
1172 
1173  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1174 
1175  switch (wmw->dwStatus) {
1176  case MCI_MODE_PLAY:
1177  dwRet = waveOutPause(wmw->hWave);
1178  if (dwRet==MMSYSERR_NOERROR) wmw->dwStatus = MCI_MODE_PAUSE;
1179  else { /* When playthread was not started yet, winmm not opened, error 5 MMSYSERR_INVALHANDLE */
1180  ERR("waveOutPause error %d\n",dwRet);
1181  dwRet = MCIERR_INTERNAL;
1182  }
1183  break;
1184  case MCI_MODE_RECORD:
1185  dwRet = waveInStop(wmw->hWave);
1186  if (dwRet==MMSYSERR_NOERROR) wmw->dwStatus = MCI_MODE_PAUSE;
1187  else {
1188  ERR("waveInStop error %d\n",dwRet);
1189  dwRet = MCIERR_INTERNAL;
1190  }
1191  break;
1192  case MCI_MODE_PAUSE:
1193  dwRet = MMSYSERR_NOERROR;
1194  break;
1195  default:
1197  }
1198  if (MMSYSERR_NOERROR==dwRet && (dwFlags & MCI_NOTIFY) && lpParms)
1200  return dwRet;
1201 }
1202 
1203 /**************************************************************************
1204  * WAVE_mciResume [internal]
1205  */
1207 {
1209  DWORD dwRet;
1210 
1211  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
1212 
1213  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1214 
1215  switch (wmw->dwStatus) {
1216  case MCI_MODE_PAUSE:
1217  /* Only update dwStatus if wave* succeeds and will exchange buffers buffers. */
1218  if (wmw->fInput) {
1219  dwRet = waveInStart(wmw->hWave);
1220  if (dwRet==MMSYSERR_NOERROR) wmw->dwStatus = MCI_MODE_RECORD;
1221  else {
1222  ERR("waveInStart error %d\n",dwRet);
1223  dwRet = MCIERR_INTERNAL;
1224  }
1225  } else {
1226  dwRet = waveOutRestart(wmw->hWave);
1227  if (dwRet==MMSYSERR_NOERROR) wmw->dwStatus = MCI_MODE_PLAY;
1228  else {
1229  ERR("waveOutRestart error %d\n",dwRet);
1230  dwRet = MCIERR_INTERNAL;
1231  }
1232  }
1233  break;
1234  case MCI_MODE_PLAY:
1235  case MCI_MODE_RECORD:
1236  dwRet = MMSYSERR_NOERROR;
1237  break;
1238  default:
1240  }
1241  if (MMSYSERR_NOERROR==dwRet && (dwFlags & MCI_NOTIFY) && lpParms)
1243  return dwRet;
1244 }
1245 
1246 /**************************************************************************
1247  * WAVE_mciSeek [internal]
1248  */
1250 {
1252  DWORD position, dwRet;
1253 
1254  TRACE("(%04X, %08X, %p);\n", wDevID, dwFlags, lpParms);
1255 
1256  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1257  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1258 
1260  if (!position) return MCIERR_MISSING_PARAMETER;
1261  if (position&(position-1)) return MCIERR_FLAGS_NOT_COMPATIBLE;
1262 
1263  /* Stop sends MCI_NOTIFY_ABORTED when needed */
1264  dwRet = WAVE_mciStop(wDevID, MCI_WAIT, 0);
1265  if (dwRet != MMSYSERR_NOERROR) return dwRet;
1266 
1267  if (dwFlags & MCI_TO) {
1268  position = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwTo);
1269  if (position > wmw->ckWaveData.cksize)
1270  return MCIERR_OUTOFRANGE;
1271  } else if (dwFlags & MCI_SEEK_TO_START) {
1272  position = 0;
1273  } else {
1274  position = wmw->ckWaveData.cksize;
1275  }
1276  /* Seek rounds down, unless at end */
1277  if (position != wmw->ckWaveData.cksize) {
1278  position /= wmw->lpWaveFormat->nBlockAlign;
1279  position *= wmw->lpWaveFormat->nBlockAlign;
1280  }
1281  wmw->dwPosition = position;
1282  TRACE("Seeking to position=%u bytes\n", position);
1283 
1284  if (dwFlags & MCI_NOTIFY)
1286 
1287  return MMSYSERR_NOERROR;
1288 }
1289 
1290 /**************************************************************************
1291  * WAVE_mciSet [internal]
1292  */
1294 {
1296 
1297  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
1298 
1299  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1300  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1301 
1302  if (dwFlags & MCI_SET_TIME_FORMAT) {
1303  switch (lpParms->dwTimeFormat) {
1305  TRACE("MCI_FORMAT_MILLISECONDS !\n");
1307  break;
1308  case MCI_FORMAT_BYTES:
1309  TRACE("MCI_FORMAT_BYTES !\n");
1311  break;
1312  case MCI_FORMAT_SAMPLES:
1313  TRACE("MCI_FORMAT_SAMPLES !\n");
1315  break;
1316  default:
1317  WARN("Bad time format %u!\n", lpParms->dwTimeFormat);
1318  return MCIERR_BAD_TIME_FORMAT;
1319  }
1320  }
1321  if (dwFlags & MCI_SET_VIDEO) {
1322  TRACE("No support for video !\n");
1324  }
1325  if (dwFlags & MCI_SET_DOOR_OPEN) {
1326  TRACE("No support for door open !\n");
1328  }
1329  if (dwFlags & MCI_SET_DOOR_CLOSED) {
1330  TRACE("No support for door close !\n");
1332  }
1333  if (dwFlags & MCI_SET_AUDIO) {
1334  if (dwFlags & MCI_SET_ON) {
1335  TRACE("MCI_SET_ON audio !\n");
1336  } else if (dwFlags & MCI_SET_OFF) {
1337  TRACE("MCI_SET_OFF audio !\n");
1338  } else {
1339  WARN("MCI_SET_AUDIO without SET_ON or SET_OFF\n");
1340  return MCIERR_BAD_INTEGER;
1341  }
1342 
1343  switch (lpParms->dwAudio)
1344  {
1345  case MCI_SET_AUDIO_ALL: TRACE("MCI_SET_AUDIO_ALL !\n"); break;
1346  case MCI_SET_AUDIO_LEFT: TRACE("MCI_SET_AUDIO_LEFT !\n"); break;
1347  case MCI_SET_AUDIO_RIGHT: TRACE("MCI_SET_AUDIO_RIGHT !\n"); break;
1348  default: WARN("Unknown audio channel %u\n", lpParms->dwAudio); break;
1349  }
1350  }
1351  if (dwFlags & MCI_WAVE_INPUT) {
1352  TRACE("MCI_WAVE_INPUT = %d\n", lpParms->wInput);
1353  if (lpParms->wInput >= waveInGetNumDevs())
1354  return MCIERR_OUTOFRANGE;
1355  if (wmw->wInput != (WORD)lpParms->wInput)
1357  wmw->wInput = lpParms->wInput;
1358  }
1359  if (dwFlags & MCI_WAVE_OUTPUT) {
1360  TRACE("MCI_WAVE_OUTPUT = %d\n", lpParms->wOutput);
1361  if (lpParms->wOutput >= waveOutGetNumDevs())
1362  return MCIERR_OUTOFRANGE;
1363  if (wmw->wOutput != (WORD)lpParms->wOutput)
1365  wmw->wOutput = lpParms->wOutput;
1366  }
1368  TRACE("MCI_WAVE_SET_ANYINPUT\n");
1369  if (wmw->wInput != (WORD)lpParms->wInput)
1371  wmw->wInput = WAVE_MAPPER;
1372  }
1374  TRACE("MCI_WAVE_SET_ANYOUTPUT\n");
1375  if (wmw->wOutput != (WORD)lpParms->wOutput)
1377  wmw->wOutput = WAVE_MAPPER;
1378  }
1379  /* Set wave format parameters is refused after Open or Record.*/
1381  TRACE("MCI_WAVE_SET_FORMATTAG = %d\n", lpParms->wFormatTag);
1382  if (wmw->lpWaveFormat != &wmw->wfxRef) return MCIERR_NONAPPLICABLE_FUNCTION;
1383  if (lpParms->wFormatTag != WAVE_FORMAT_PCM)
1384  return MCIERR_OUTOFRANGE;
1385  }
1387  if (wmw->lpWaveFormat != &wmw->wfxRef) return MCIERR_NONAPPLICABLE_FUNCTION;
1388  wmw->wfxRef.nAvgBytesPerSec = lpParms->nAvgBytesPerSec;
1389  TRACE("MCI_WAVE_SET_AVGBYTESPERSEC = %d\n", wmw->wfxRef.nAvgBytesPerSec);
1390  }
1392  if (wmw->lpWaveFormat != &wmw->wfxRef) return MCIERR_NONAPPLICABLE_FUNCTION;
1393  wmw->wfxRef.wBitsPerSample = lpParms->wBitsPerSample;
1394  TRACE("MCI_WAVE_SET_BITSPERSAMPLE = %d\n", wmw->wfxRef.wBitsPerSample);
1395  }
1397  if (wmw->lpWaveFormat != &wmw->wfxRef) return MCIERR_NONAPPLICABLE_FUNCTION;
1398  wmw->wfxRef.nBlockAlign = lpParms->nBlockAlign;
1399  TRACE("MCI_WAVE_SET_BLOCKALIGN = %d\n", wmw->wfxRef.nBlockAlign);
1400  }
1402  if (wmw->lpWaveFormat != &wmw->wfxRef) return MCIERR_NONAPPLICABLE_FUNCTION;
1403  wmw->wfxRef.nChannels = lpParms->nChannels;
1404  TRACE("MCI_WAVE_SET_CHANNELS = %d\n", wmw->wfxRef.nChannels);
1405  }
1407  if (wmw->lpWaveFormat != &wmw->wfxRef) return MCIERR_NONAPPLICABLE_FUNCTION;
1408  wmw->wfxRef.nSamplesPerSec = lpParms->nSamplesPerSec;
1409  TRACE("MCI_WAVE_SET_SAMPLESPERSEC = %d\n", wmw->wfxRef.nSamplesPerSec);
1410  }
1411  if (dwFlags & MCI_NOTIFY)
1413  return 0;
1414 }
1415 
1416 /**************************************************************************
1417  * WAVE_mciSave [internal]
1418  */
1420 {
1422  DWORD ret = MCIERR_FILE_NOT_SAVED, tmpRet;
1423 
1424  TRACE("%d, %08X, %p);\n", wDevID, dwFlags, lpParms);
1425  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1426  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1427 
1428  if (dwFlags & MCI_WAIT)
1429  {
1430  FIXME("MCI_WAIT not implemented\n");
1431  }
1432  WAVE_mciStop(wDevID, 0, NULL);
1433 
1434  ret = mmioAscend(wmw->hFile, &wmw->ckWaveData, 0);
1435  ret = mmioAscend(wmw->hFile, &wmw->ckMainRIFF, 0);
1436 
1437  ret = mmioClose(wmw->hFile, 0);
1438  wmw->hFile = 0;
1439 
1440  /*
1441  If the destination file already exists, it has to be overwritten. (Behaviour
1442  verified in Windows (2000)). If it doesn't overwrite, it is breaking one of
1443  my applications. We are making use of mmioRename, which WILL NOT overwrite
1444  the destination file (which is what Windows does, also verified in Win2K)
1445  So, lets delete the destination file before calling mmioRename. If the
1446  destination file DOESN'T exist, the delete will fail silently. Let's also be
1447  careful not to lose our previous error code.
1448  */
1449  tmpRet = GetLastError();
1450  DeleteFileW (lpParms->lpfilename);
1451  SetLastError(tmpRet);
1452 
1453  /* FIXME: Open file.wav; Save; must not rename the original file.
1454  * Nor must Save a.wav; Save b.wav rename a. */
1455  if (0 == mmioRenameW(wmw->lpFileName, lpParms->lpfilename, 0, 0 )) {
1457  }
1458 
1459  if (MMSYSERR_NOERROR==ret && (dwFlags & MCI_NOTIFY))
1461 
1462  if (ret == MMSYSERR_NOERROR)
1463  ret = WAVE_mciOpenFile(wmw, lpParms->lpfilename);
1464 
1465  return ret;
1466 }
1467 
1468 /**************************************************************************
1469  * WAVE_mciStatus [internal]
1470  */
1472 {
1474  DWORD ret = 0;
1475 
1476  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
1477  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1478  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1480 
1481  if (dwFlags & MCI_STATUS_ITEM) {
1482  switch (lpParms->dwItem) {
1484  lpParms->dwReturn = 1;
1485  TRACE("MCI_STATUS_CURRENT_TRACK => %lu\n", lpParms->dwReturn);
1486  break;
1487  case MCI_STATUS_LENGTH:
1488  if (!wmw->hFile) {
1489  lpParms->dwReturn = 0;
1491  }
1492  /* only one track in file is currently handled, so don't take care of MCI_TRACK flag */
1494  TRACE("MCI_STATUS_LENGTH => %lu\n", lpParms->dwReturn);
1495  break;
1496  case MCI_STATUS_MODE:
1497  TRACE("MCI_STATUS_MODE => %u\n", wmw->dwStatus);
1498  lpParms->dwReturn = MAKEMCIRESOURCE(wmw->dwStatus, wmw->dwStatus);
1500  break;
1502  TRACE("MCI_STATUS_MEDIA_PRESENT => TRUE!\n");
1503  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1505  break;
1507  /* only one track in file is currently handled, so don't take care of MCI_TRACK flag */
1508  lpParms->dwReturn = 1;
1509  TRACE("MCI_STATUS_NUMBER_OF_TRACKS => %lu\n", lpParms->dwReturn);
1510  break;
1511  case MCI_STATUS_POSITION:
1512  if (!wmw->hFile) {
1513  lpParms->dwReturn = 0;
1515  }
1516  /* only one track in file is currently handled, so don't take care of MCI_TRACK flag */
1517  lpParms->dwReturn = WAVE_ConvertByteToTimeFormat(wmw,
1518  (dwFlags & MCI_STATUS_START) ? 0 : wmw->dwPosition);
1519  TRACE("MCI_STATUS_POSITION %s => %lu\n",
1520  (dwFlags & MCI_STATUS_START) ? "start" : "current", lpParms->dwReturn);
1521  break;
1522  case MCI_STATUS_READY:
1523  lpParms->dwReturn = (wmw->dwStatus == MCI_MODE_NOT_READY) ?
1525  TRACE("MCI_STATUS_READY => %u!\n", LOWORD(lpParms->dwReturn));
1527  break;
1530  TRACE("MCI_STATUS_TIME_FORMAT => %lu\n", lpParms->dwReturn);
1532  break;
1533  case MCI_WAVE_INPUT:
1534  if (wmw->wInput != (WORD)WAVE_MAPPER)
1535  lpParms->dwReturn = wmw->wInput;
1536  else {
1539  }
1540  TRACE("MCI_WAVE_INPUT => %d\n", (signed)wmw->wInput);
1541  break;
1542  case MCI_WAVE_OUTPUT:
1543  if (wmw->wOutput != (WORD)WAVE_MAPPER)
1544  lpParms->dwReturn = wmw->wOutput;
1545  else {
1548  }
1549  TRACE("MCI_WAVE_OUTPUT => %d\n", (signed)wmw->wOutput);
1550  break;
1551  /* It is always ok to query wave format parameters,
1552  * except on auto-open yield MCIERR_UNSUPPORTED_FUNCTION. */
1555  lpParms->dwReturn = wmw->lpWaveFormat->wFormatTag;
1556  else {
1559  }
1560  TRACE("MCI_WAVE_FORMATTAG => %lu\n", lpParms->dwReturn);
1561  break;
1563  lpParms->dwReturn = wmw->lpWaveFormat->nAvgBytesPerSec;
1564  TRACE("MCI_WAVE_STATUS_AVGBYTESPERSEC => %lu\n", lpParms->dwReturn);
1565  break;
1567  lpParms->dwReturn = wmw->lpWaveFormat->wBitsPerSample;
1568  TRACE("MCI_WAVE_STATUS_BITSPERSAMPLE => %lu\n", lpParms->dwReturn);
1569  break;
1571  lpParms->dwReturn = wmw->lpWaveFormat->nBlockAlign;
1572  TRACE("MCI_WAVE_STATUS_BLOCKALIGN => %lu\n", lpParms->dwReturn);
1573  break;
1575  lpParms->dwReturn = wmw->lpWaveFormat->nChannels;
1576  TRACE("MCI_WAVE_STATUS_CHANNELS => %lu\n", lpParms->dwReturn);
1577  break;
1579  lpParms->dwReturn = wmw->lpWaveFormat->nSamplesPerSec;
1580  TRACE("MCI_WAVE_STATUS_SAMPLESPERSEC => %lu\n", lpParms->dwReturn);
1581  break;
1582  case MCI_WAVE_STATUS_LEVEL:
1583  TRACE("MCI_WAVE_STATUS_LEVEL !\n");
1584  lpParms->dwReturn = 0xAAAA5555;
1585  break;
1586  default:
1587  WARN("unknown command %08X !\n", lpParms->dwItem);
1589  }
1590  }
1591  if ((dwFlags & MCI_NOTIFY) && HRESULT_CODE(ret)==0)
1593  return ret;
1594 }
1595 
1596 /**************************************************************************
1597  * WAVE_mciGetDevCaps [internal]
1598  */
1600  LPMCI_GETDEVCAPS_PARMS lpParms)
1601 {
1603  DWORD ret = 0;
1604 
1605  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
1606 
1607  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1608  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1609 
1610  if (dwFlags & MCI_GETDEVCAPS_ITEM) {
1611  switch(lpParms->dwItem) {
1615  break;
1617  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1619  break;
1621  lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
1623  break;
1625  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1627  break;
1629  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1631  break;
1633  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1635  break;
1637  lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
1639  break;
1641  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1643  break;
1645  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1647  break;
1649  lpParms->dwReturn = waveInGetNumDevs();
1650  break;
1652  lpParms->dwReturn = waveOutGetNumDevs();
1653  break;
1654  default:
1655  FIXME("Unknown capability (%08x) !\n", lpParms->dwItem);
1657  }
1658  } else {
1659  WARN("No GetDevCaps-Item !\n");
1661  }
1662  if ((dwFlags & MCI_NOTIFY) && HRESULT_CODE(ret)==0)
1664  return ret;
1665 }
1666 
1667 /**************************************************************************
1668  * WAVE_mciInfo [internal]
1669  */
1671 {
1672  DWORD ret = 0;
1673  LPCWSTR str = 0;
1675 
1676  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
1677 
1678  if (!lpParms || !lpParms->lpstrReturn)
1680 
1681  TRACE("buf=%p, len=%u\n", lpParms->lpstrReturn, lpParms->dwRetSize);
1682 
1683  if (wmw == NULL) {
1685  } else {
1686  static const WCHAR wszAudio [] = {'W','i','n','e','\'','s',' ','a','u','d','i','o',' ','p','l','a','y','e','r',0};
1687  static const WCHAR wszWaveIn [] = {'W','i','n','e',' ','W','a','v','e',' ','I','n',0};
1688  static const WCHAR wszWaveOut[] = {'W','i','n','e',' ','W','a','v','e',' ','O','u','t',0};
1689 
1690  switch (dwFlags & ~(MCI_WAIT|MCI_NOTIFY)) {
1691  case MCI_INFO_PRODUCT: str = wszAudio; break;
1692  case MCI_INFO_FILE: str = wmw->lpFileName; break;
1693  case MCI_WAVE_INPUT: str = wszWaveIn; break;
1694  case MCI_WAVE_OUTPUT: str = wszWaveOut; break;
1695  default:
1696  WARN("Don't know this info command (%u)\n", dwFlags);
1698  }
1699  }
1700  if (!ret) {
1701  if (lpParms->dwRetSize) {
1702  WCHAR zero = 0;
1703  /* FIXME? Since NT, mciwave, mciseq and mcicda set dwRetSize
1704  * to the number of characters written, excluding \0. */
1705  lstrcpynW(lpParms->lpstrReturn, str ? str : &zero, lpParms->dwRetSize);
1706  } else ret = MCIERR_PARAM_OVERFLOW;
1707  }
1708  if (MMSYSERR_NOERROR==ret && (dwFlags & MCI_NOTIFY))
1710  return ret;
1711 }
1712 
1713 /**************************************************************************
1714  * DriverProc (MCIWAVE.@)
1715  */
1716 LRESULT CALLBACK MCIWAVE_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
1718 {
1719  TRACE("(%08lX, %p, %08X, %08lX, %08lX)\n",
1720  dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1721 
1722  switch (wMsg) {
1723  case DRV_LOAD: return 1;
1724  case DRV_FREE: return 1;
1726  case DRV_CLOSE: return WAVE_drvClose(dwDevID);
1727  case DRV_ENABLE: return 1;
1728  case DRV_DISABLE: return 1;
1729  case DRV_QUERYCONFIGURE: return 1;
1730  case DRV_CONFIGURE: MessageBoxA(0, "MCI waveaudio Driver !", "Wine Driver", MB_OK); return 1;
1731  case DRV_INSTALL: return DRVCNF_RESTART;
1732  case DRV_REMOVE: return DRVCNF_RESTART;
1733  }
1734 
1735  if (dwDevID == 0xFFFFFFFF) return MCIERR_UNSUPPORTED_FUNCTION;
1736 
1737  switch (wMsg) {
1740  case MCI_CUE: return WAVE_mciCue (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
1741  case MCI_PLAY: return WAVE_mciPlay (dwDevID, dwParam1, dwParam2, NULL);
1742  case MCI_RECORD: return WAVE_mciRecord (dwDevID, dwParam1, dwParam2, NULL);
1743  case MCI_STOP: return WAVE_mciStop (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
1744  case MCI_SET: return WAVE_mciSet (dwDevID, dwParam1, (LPMCI_WAVE_SET_PARMS) dwParam2);
1745  case MCI_PAUSE: return WAVE_mciPause (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
1746  case MCI_RESUME: return WAVE_mciResume (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
1747  case MCI_STATUS: return WAVE_mciStatus (dwDevID, dwParam1, (LPMCI_STATUS_PARMS) dwParam2);
1749  case MCI_INFO: return WAVE_mciInfo (dwDevID, dwParam1, (LPMCI_INFO_PARMSW) dwParam2);
1750  case MCI_SEEK: return WAVE_mciSeek (dwDevID, dwParam1, (LPMCI_SEEK_PARMS) dwParam2);
1751  case MCI_SAVE: return WAVE_mciSave (dwDevID, dwParam1, (LPMCI_SAVE_PARMSW) dwParam2);
1752  /* commands that should be supported */
1753  case MCI_LOAD:
1754  case MCI_FREEZE:
1755  case MCI_PUT:
1756  case MCI_REALIZE:
1757  case MCI_UNFREEZE:
1758  case MCI_UPDATE:
1759  case MCI_WHERE:
1760  case MCI_STEP:
1761  case MCI_SPIN:
1762  case MCI_ESCAPE:
1763  case MCI_COPY:
1764  case MCI_CUT:
1765  case MCI_DELETE:
1766  case MCI_PASTE:
1767  FIXME("Unsupported command [%u]\n", wMsg);
1768  break;
1769  case MCI_WINDOW:
1770  TRACE("Unsupported command [%u]\n", wMsg);
1771  break;
1772  /* option which can be silenced */
1773  case MCI_CONFIGURE:
1774  return 0;
1775  case MCI_OPEN:
1776  case MCI_CLOSE:
1777  ERR("Shouldn't receive a MCI_OPEN or CLOSE message\n");
1778  break;
1779  default:
1780  FIXME("is probably wrong msg [%u]\n", wMsg);
1781  return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1782  }
1784 }
#define MCI_WAVE_GETDEVCAPS_INPUTS
Definition: mmsystem.h:839
Definition: mciwave.c:71
#define DRV_DISABLE
Definition: mmsystem.h:123
#define MMIO_ALLOCBUF
Definition: mmsystem.h:532
BOOL WINAPI mciSetDriverData(UINT uDeviceID, DWORD dwData)
#define MCI_FORMAT_SAMPLES
Definition: mmsystem.h:710
#define MCI_UNFREEZE
Definition: mmsystem.h:669
#define MCI_NO_COMMAND_TABLE
Definition: mmddk.h:375
#define WOM_DONE
Definition: mmsystem.h:183
#define MCIERR_NONAPPLICABLE_FUNCTION
Definition: mmsystem.h:610
#define MCI_ESCAPE
Definition: mmsystem.h:648
#define MCI_MODE_STOP
Definition: mmsystem.h:695
static void CALLBACK WAVE_mciPlayCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, LPARAM dwParam1, LPARAM dwParam2)
Definition: mciwave.c:700
#define MCIERR_INVALID_FILE
Definition: mmsystem.h:604
UINT WINAPI waveInClose(HWAVEIN hWaveIn)
Definition: winmm.c:2637
DWORD WINAPI mciGetDriverData(UINT uDeviceID)
Definition: mci.c:2066
#define WAVE_FORMAT_PCM_S
Definition: mmddk.h:358
#define MMIO_READWRITE
Definition: mmsystem.h:537
DWORD_PTR dwCallback
Definition: mmsystem.h:1691
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:407
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
static DWORD WAVE_mciPlay(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt, HANDLE hEvent)
Definition: mciwave.c:739
#define MCI_WAVE_STATUS_BITSPERSAMPLE
Definition: mmsystem.h:835
#define MCI_INFO_PRODUCT
Definition: mmsystem.h:752
#define MCI_WAVE_STATUS_SAMPLESPERSEC
Definition: mmsystem.h:832
#define MCI_COPY
Definition: mmsystem.h:672
static struct object_header ** handles
Definition: handle.c:45
#define MCI_STATUS_ITEM
Definition: mmsystem.h:742
#define DWORD_PTR
Definition: treelist.c:76
#define MCI_WAVE_SET_CHANNELS
Definition: mmsystem.h:823
#define MCI_WAIT
Definition: mmsystem.h:730
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
DWORD_PTR dwCallback
Definition: mmsystem.h:1624
static void WAVE_mciNotify(DWORD_PTR hWndCallBack, WINE_MCIWAVE *wmw, UINT wStatus)
Definition: mciwave.c:213
MMRESULT WINAPI waveInOpen(HWAVEIN *lphWaveIn, UINT uDeviceID, LPCWAVEFORMATEX lpFormat, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD dwFlags)
Definition: winmm.c:2626
Definition: ftp_var.h:139
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
#define MCI_WAVE_INPUT
Definition: mmsystem.h:828
#define MCI_STATUS_NUMBER_OF_TRACKS
Definition: mmsystem.h:746
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define MCI_GETDEVCAPS_CAN_SAVE
Definition: mmsystem.h:767
LPCWSTR lpfilename
Definition: mmsystem.h:1625
struct wavehdr_tag * LPWAVEHDR
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define MCI_WAVE_STATUS_CHANNELS
Definition: mmsystem.h:831
DWORD nAvgBytesPerSec
Definition: mmreg.h:81
MMRESULT WINAPI mmioAscend(HMMIO hmmio, LPMMCKINFO lpck, UINT uFlags)
Definition: mmio.c:1204
WORD nChannels
Definition: mmreg.h:79
#define MCIERR_UNSUPPORTED_FUNCTION
Definition: mmsystem.h:584
#define WARN(fmt,...)
Definition: debug.h:112
static DWORD WAVE_mciSave(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_SAVE_PARMSW lpParms)
Definition: mciwave.c:1419
DWORD dwDataOffset
Definition: mmsystem.h:1510
HANDLE evt
Definition: mciwave.c:73
HMMIO hFile
Definition: mciwave.c:42
#define MCI_STEP
Definition: mmsystem.h:657
#define CALLBACK
Definition: compat.h:27
DWORD_PTR dwCallback
Definition: mmsystem.h:1537
#define WAVE_MAPPER_S
Definition: mmddk.h:359
#define MCI_PASTE
Definition: mmsystem.h:673
#define assert(x)
Definition: debug.h:53
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
static DWORD WAVE_mciPause(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
Definition: mciwave.c:1166
#define MCI_GETDEVCAPS_COMPOUND_DEVICE
Definition: mmsystem.h:764
MMRESULT WINAPI mmioClose(HMMIO hmmio, UINT uFlags)
Definition: mmio.c:701
#define MCI_SET_OFF
Definition: mmsystem.h:778
#define MCI_PLAY
Definition: mmsystem.h:649
#define DRV_CLOSE
Definition: mmsystem.h:122
static DWORD WAVE_ConvertByteToTimeFormat(WINE_MCIWAVE *wmw, DWORD val)
Definition: mciwave.c:227
#define MCI_RESUME
Definition: mmsystem.h:675
char * cmd
Definition: vfdcmd.c:85
#define MCI_WAVE_STATUS_FORMATTAG
Definition: mmsystem.h:830
#define MCI_WAVE_SET_FORMATTAG
Definition: mmsystem.h:822
#define MCI_SET_AUDIO
Definition: mmsystem.h:775
#define MCI_WAVE_STATUS_BLOCKALIGN
Definition: mmsystem.h:834
HMMIO WINAPI mmioOpenW(LPWSTR szFileName, MMIOINFO *lpmmioinfo, DWORD dwOpenFlags)
Definition: mmio.c:669
LPSTR lpData
Definition: mmsystem.h:1014
GLuint GLuint end
Definition: gl.h:1545
#define MCI_RESOURCE_RETURNED
Definition: mmddk.h:369
#define MMIO_DENYWRITE
Definition: mmsystem.h:540
#define MCI_FREEZE
Definition: mmsystem.h:668
GLenum GLuint GLsizei bufsize
Definition: glext.h:7473
#define MCI_GETDEVCAPS_CAN_RECORD
Definition: mmsystem.h:759
char * LPSTR
Definition: xmlstorage.h:182
#define MAKEMCIRESOURCE(wRet, wRes)
Definition: mmddk.h:388
#define MCI_SET_DOOR_CLOSED
Definition: mmsystem.h:773
const char * filename
Definition: ioapi.h:135
struct pcmwaveformat_tag PCMWAVEFORMAT
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
#define WOM_OPEN
Definition: mmsystem.h:181
#define lstrlenW
Definition: compat.h:416
async_cmd cmd
Definition: mciwave.c:72
#define MCI_STATUS_POSITION
Definition: mmsystem.h:745
#define DWORD
Definition: nt_native.h:44
UINT WINAPI waveInPrepareHeader(HWAVEIN hWaveIn, WAVEHDR *lpWaveInHdr, UINT uSize)
Definition: winmm.c:2656
LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, INT iOrigin)
Definition: mmio.c:835
#define MCI_CUE
Definition: mmsystem.h:663
#define MCI_SAVE
Definition: mmsystem.h:661
#define MCI_NOTIFY_ABORTED
Definition: mmsystem.h:727
HANDLE hCallback
Definition: mciwave.c:44
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
UINT WINAPI waveOutPrepareHeader(HWAVEOUT hWaveOut, WAVEHDR *lpWaveOutHdr, UINT uSize)
Definition: winmm.c:2280
#define lstrcpynW
Definition: compat.h:406
static HANDLE hEvent
Definition: comm.c:54
#define DRV_QUERYCONFIGURE
Definition: mmsystem.h:126
#define DRV_OPEN
Definition: mmsystem.h:121
WINE_DEFAULT_DEBUG_CHANNEL(mciwave)
#define MCI_STOP
Definition: mmsystem.h:651
#define MCI_WINDOW
Definition: mmsystem.h:665
int WINAPI MessageBoxA(_In_opt_ HWND, _In_opt_ LPCSTR, _In_opt_ LPCSTR, _In_ UINT)
DWORD dwLoops
Definition: mmsystem.h:1019
DWORD_PTR dwReturn
Definition: mmsystem.h:1567
static LRESULT WAVE_mciOpenFile(WINE_MCIWAVE *wmw, LPCWSTR filename)
Definition: mciwave.c:461
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
BOOL WINAPI mciDriverNotify(HWND hwndCallback, UINT uDeviceID, UINT uStatus)
Definition: mci.c:2056
volatile WORD dwStatus
Definition: mciwave.c:51
#define MCI_GETDEVCAPS_USES_FILES
Definition: mmsystem.h:763
#define MCI_SET
Definition: mmsystem.h:656
#define MCIERR_FILE_NOT_SAVED
Definition: mmsystem.h:594
#define WOM_CLOSE
Definition: mmsystem.h:182
#define MCI_MODE_RECORD
Definition: mmsystem.h:697
DWORD dwPosition
Definition: mciwave.c:53
#define WAVE_FORMAT_PCM
Definition: constants.h:425
#define WIM_CLOSE
Definition: mmsystem.h:185
DWORD WINAPI GetTempPathW(IN DWORD count, OUT LPWSTR path)
Definition: path.c:2079
#define MCI_OPEN_ELEMENT_ID
Definition: mmsystem.h:737
#define MCIERR_FLAGS_NOT_COMPATIBLE
Definition: mmsystem.h:593
#define MCI_FORMAT_MILLISECONDS
Definition: mmsystem.h:701
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
#define MCI_RECORD
Definition: mmsystem.h:658
UINT wCustomCommandTable
Definition: mmddk.h:438
#define CALLBACK_FUNCTION
Definition: mmsystem.h:150
DWORD dwFlags
Definition: mmsystem.h:1018
WAVEFORMATEX wfxRef
Definition: mciwave.c:46
#define debugstr_w
Definition: kernel32.h:32
#define MCI_MODE_PLAY
Definition: mmsystem.h:696
#define FIXME(fmt,...)
Definition: debug.h:111
WORD wBitsPerSample
Definition: audioclient.idl:45
static LRESULT WAVE_drvClose(MCIDEVICEID dwDevID)
Definition: mciwave.c:180
DWORD(* async_cmd)(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt, HANDLE evt)
Definition: mciwave.c:69
UINT WINAPI waveInUnprepareHeader(HWAVEIN hWaveIn, WAVEHDR *lpWaveInHdr, UINT uSize)
Definition: winmm.c:2687
#define MCI_WAVE_SET_SAMPLESPERSEC
Definition: mmsystem.h:824
#define MCI_WHERE
Definition: mmsystem.h:667
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
#define MCI_GETDEVCAPS_DEVICE_TYPE
Definition: mmsystem.h:762
#define MCI_WAVE_STATUS_LEVEL
Definition: mmsystem.h:836
LONG WINAPI mmioWrite(HMMIO hmmio, HPCSTR pch, LONG cch)
Definition: mmio.c:781
const WCHAR * str
#define WIM_OPEN
Definition: mmsystem.h:184
#define MCI_INFO_FILE
Definition: mmsystem.h:753
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:136
#define MCI_WAVE_OUTPUT
Definition: mmsystem.h:829
smooth NULL
Definition: ftsmooth.c:416
static void WAVE_mciPlayWaitDone(WINE_MCIWAVE *wmw)
Definition: mciwave.c:723
LONG_PTR LPARAM
Definition: windef.h:208
#define DRV_LOAD(x)
DWORD_PTR dwCallback
Definition: mmsystem.h:1579
#define MMIO_FINDCHUNK
Definition: mmsystem.h:551
#define MCI_OPEN
Definition: mmsystem.h:646
static DWORD WAVE_mciCue(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
Definition: mciwave.c:581
BOOL fInput
Definition: mciwave.c:48
#define MCI_WAVE_SET_ANYOUTPUT
Definition: mmsystem.h:838
FOURCC fccType
Definition: mmsystem.h:1509
UINT WINAPI waveOutGetNumDevs(void)
Definition: winmm.c:2140
#define MCIERR_MISSING_PARAMETER
Definition: mmsystem.h:583
#define DRVCNF_RESTART
Definition: mmsystem.h:135
#define DRV_REMOVE
Definition: mmsystem.h:128
#define MCI_INFO
Definition: mmsystem.h:653
WORD wOutput
Definition: mciwave.c:50
#define MCI_NOTIFY_FAILURE
Definition: mmsystem.h:728
BOOL WINAPI SetThreadPriority(IN HANDLE hThread, IN int nPriority)
Definition: thread.c:699
#define MCI_GETDEVCAPS_HAS_VIDEO
Definition: mmsystem.h:761
DWORD nSamplesPerSec
Definition: audioclient.idl:42
#define MCI_CONFIGURE
Definition: digitalv.h:45
GLuint GLfloat * val
Definition: glext.h:7180
#define MCI_OPEN_DRIVER
Definition: mmddk.h:338
#define MMIO_READ
Definition: mmsystem.h:535
#define MCIERR_PARAM_OVERFLOW
Definition: mmsystem.h:578
#define MCI_STATUS
Definition: mmsystem.h:662
#define MCIERR_OUT_OF_MEMORY
Definition: mmsystem.h:574
#define SEEK_SET
Definition: jmemansi.c:26
static DWORD WAVE_mciCreateRIFFSkeleton(WINE_MCIWAVE *wmw)
Definition: mciwave.c:346
#define TRACE(s)
Definition: solgame.cpp:4
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define MCI_SET_ON
Definition: mmsystem.h:777
GLsizeiptr size
Definition: glext.h:5919
DWORD_PTR dwParam2
Definition: mciwave.c:76
LPWSTR lpFileName
Definition: mciwave.c:45
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define WAVE_MAPPER
Definition: mmsystem.h:187
#define GetProcessHeap()
Definition: compat.h:404
LPWAVEFORMATEX lpWaveFormat
Definition: mciwave.c:47
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define MCI_STATUS_LENGTH
Definition: mmsystem.h:744
#define DRV_CONFIGURE
Definition: mmsystem.h:125
#define MCIERR_BAD_INTEGER
Definition: mmsystem.h:580
__wchar_t WCHAR
Definition: xmlstorage.h:180
UINT WINAPI waveOutPause(HWAVEOUT hWaveOut)
Definition: winmm.c:2374
static DWORD WAVE_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
Definition: mciwave.c:1206
#define MCI_OPEN_SHAREABLE
Definition: mmsystem.h:734
#define MCI_SET_TIME_FORMAT
Definition: mmsystem.h:774
#define MCI_SET_AUDIO_LEFT
Definition: mmsystem.h:780
static LRESULT WAVE_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp)
Definition: mciwave.c:150
#define MCIERR_BAD_TIME_FORMAT
Definition: mmsystem.h:601
MCIDEVICEID wNotifyDeviceID
Definition: mciwave.c:43
#define MAX_PATH
Definition: compat.h:26
WORD wInput
Definition: mciwave.c:49
#define MCI_REALIZE
Definition: mmsystem.h:664
UINT WINAPI GetTempFileNameW(IN LPCWSTR lpPathName, IN LPCWSTR lpPrefixString, IN UINT uUnique, OUT LPWSTR lpTempFileName)
Definition: filename.c:84
unsigned short WORD
Definition: ntddk_ex.h:93
#define MCI_WAVE_SET_AVGBYTESPERSEC
Definition: mmsystem.h:825
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint left
Definition: glext.h:7726
#define SetLastError(x)
Definition: compat.h:418
#define DRV_FREE
Definition: mmsystem.h:124
DWORD cksize
Definition: mmsystem.h:1508
#define MCI_WAVE_SET_ANYINPUT
Definition: mmsystem.h:837
#define MCI_STATUS_MODE
Definition: mmsystem.h:747
#define MCI_STATUS_START
Definition: mmsystem.h:743
DWORD_PTR dwCallback
Definition: mmsystem.h:1543
UINT WINAPI waveOutWrite(HWAVEOUT hWaveOut, LPWAVEHDR lpWaveOutHdr, UINT uSize)
Definition: winmm.c:2344
#define MCI_NOTIFY_SUCCESSFUL
Definition: mmsystem.h:725
WORD wFormatTag
Definition: mmreg.h:78
static DWORD MCI_SendCommandAsync(UINT wDevID, async_cmd cmd, DWORD_PTR dwParam1, DWORD_PTR dwParam2, UINT size)
Definition: mciwave.c:99
#define THREAD_PRIORITY_TIME_CRITICAL
Definition: winbase.h:278
static double zero
Definition: j0_y0.c:96
int ret
static DWORD WAVE_mciRecord(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt, HANDLE hEvent)
Definition: mciwave.c:1000
#define MCI_WAVE_STATUS_AVGBYTESPERSEC
Definition: mmsystem.h:833
#define MCI_SET_AUDIO_RIGHT
Definition: mmsystem.h:781
static void WAVE_mciDefaultFmt(WINE_MCIWAVE *wmw)
Definition: mciwave.c:331
char * HPSTR
Definition: mmsystem.h:1477
static const WCHAR L[]
Definition: oid.c:1250
#define FOURCC_RIFF
Definition: mmsystem.h:564
#define InterlockedDecrement
Definition: armddk.h:52
#define MCI_LOAD
Definition: mmsystem.h:670
MMRESULT WINAPI mmioCreateChunk(HMMIO hmmio, MMCKINFO *lpck, UINT uFlags)
Definition: mmio.c:1238
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
UINT WINAPI waveInAddBuffer(HWAVEIN hWaveIn, WAVEHDR *lpWaveInHdr, UINT uSize)
Definition: winmm.c:2720
#define mmioFOURCC(c0, c1, c2, c3)
Definition: mmsystem.h:38
#define MCI_GETDEVCAPS_HAS_AUDIO
Definition: mmsystem.h:760
static WINE_MCIWAVE * WAVE_mciGetOpenDev(MCIDEVICEID wDevID)
Definition: mciwave.c:195
DWORD dwBufferLength
Definition: mmsystem.h:1015
#define MCIERR_INTERNAL
Definition: mmsystem.h:587
#define MCI_STATUS_CURRENT_TRACK
Definition: mmsystem.h:751
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define MCI_CUT
Definition: mmsystem.h:671
#define MCI_SEEK_TO_END
Definition: mmsystem.h:741
#define MCIERR_OUTOFRANGE
Definition: mmsystem.h:592
#define MCI_GETDEVCAPS_ITEM
Definition: mmsystem.h:758
#define MCI_FALSE
Definition: mmddk.h:340
#define err(...)
static void WAVE_mciRecordWaitDone(WINE_MCIWAVE *wmw)
Definition: mciwave.c:984
static DWORD WAVE_mciReadFmt(WINE_MCIWAVE *wmw, const MMCKINFO *pckMainRIFF)
Definition: mciwave.c:278
UINT wDevID
Definition: mciwave.c:39
uint32_t DWORD_PTR
Definition: typedefs.h:64
_In_ HANDLE hFile
Definition: mswsock.h:90
UINT WINAPI waveOutUnprepareHeader(HWAVEOUT hWaveOut, LPWAVEHDR lpWaveOutHdr, UINT uSize)
Definition: winmm.c:2310
#define MCI_CLOSE_DRIVER
Definition: mmddk.h:339
static void CALLBACK WAVE_mciRecordCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, LPARAM dwParam1, LPARAM dwParam2)
Definition: mciwave.c:941
#define MMIO_CREATERIFF
Definition: mmsystem.h:554
#define MCI_SEEK_TO_START
Definition: mmsystem.h:740
#define DRV_ENABLE
Definition: mmsystem.h:120
UINT WINAPI waveInStart(HWAVEIN hWaveIn)
Definition: winmm.c:2752
UINT WINAPI waveInReset(HWAVEIN hWaveIn)
Definition: winmm.c:2737
#define ERR(fmt,...)
Definition: debug.h:110
static DWORD WAVE_mciSeek(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
Definition: mciwave.c:1249
DWORD_PTR dwCallback
Definition: mmsystem.h:1566
MMCKINFO ckWaveData
Definition: mciwave.c:57
#define HWND_32(h16)
Definition: wownt32.h:29
static DWORD WAVE_mciStop(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
Definition: mciwave.c:618
MMCKINFO ckMainRIFF
Definition: mciwave.c:56
#define MCIERR_FILE_NOT_FOUND
Definition: mmsystem.h:585
#define InterlockedIncrement
Definition: armddk.h:53
#define lstrcpyW
Definition: compat.h:415
#define MCI_WAVE_SET_BITSPERSAMPLE
Definition: mmsystem.h:827
#define MCI_MODE_NOT_READY
Definition: mmsystem.h:694
MMRESULT WINAPI waveOutOpen(LPHWAVEOUT lphWaveOut, UINT uDeviceID, LPCWAVEFORMATEX lpFormat, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD dwFlags)
Definition: winmm.c:2249
UINT WINAPI waveInStop(HWAVEIN hWaveIn)
Definition: winmm.c:2767
#define MCI_SET_VIDEO
Definition: mmsystem.h:776
#define MCI_NOTIFY_SUPERSEDED
Definition: mmsystem.h:726
FOURCC ckid
Definition: mmsystem.h:1507
MCIDEVICEID wDeviceID
Definition: mmsystem.h:1677
#define MCI_PUT
Definition: mmsystem.h:666
#define ARRAY_SIZE(a)
Definition: main.h:24
DWORD_PTR dwCallback
Definition: mmsystem.h:1517
MMRESULT WINAPI mmioDescend(HMMIO hmmio, LPMMCKINFO lpck, const MMCKINFO *lpckParent, UINT uFlags)
Definition: mmio.c:1106
DWORD nAvgBytesPerSec
Definition: audioclient.idl:43
WORD cbSize
Definition: mmreg.h:84
static DWORD WAVE_mciStatus(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
Definition: mciwave.c:1471
#define MCI_OPEN_ELEMENT
Definition: mmsystem.h:735
static LRESULT WAVE_mciOpen(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMSW lpOpenParms)
Definition: mciwave.c:514
DWORD_PTR dwParam1
Definition: mciwave.c:75
static DWORD create_tmp_file(HMMIO *hFile, LPWSTR *pszTmpFileName)
Definition: mciwave.c:418
LRESULT CALLBACK MCIWAVE_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, LPARAM dwParam1, LPARAM dwParam2)
Definition: mciwave.c:1716
#define min(a, b)
Definition: monoChain.cc:55
UINT WINAPI waveOutClose(HWAVEOUT hWaveOut)
Definition: winmm.c:2260
HANDLE hEvent
Definition: mciwave.c:54
unsigned int UINT
Definition: ndis.h:50
#define MB_OK
Definition: winuser.h:784
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define MCI_CLOSE
Definition: mmsystem.h:647
#define MCI_GETDEVCAPS
Definition: mmsystem.h:654
HANDLE hWave
Definition: mciwave.c:40
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:714
#define MCIERR_UNRECOGNIZED_KEYWORD
Definition: mmsystem.h:570
DWORD_PTR dwUser
Definition: mmsystem.h:1017
#define MCI_TRUE
Definition: mmddk.h:341
UINT wDevID
Definition: mciwave.c:74
UINT MCIDEVICEID
Definition: mmsystem.h:959
static DWORD WAVE_mciGetDevCaps(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_GETDEVCAPS_PARMS lpParms)
Definition: mciwave.c:1599
MMRESULT WINAPI mmioRenameW(LPCWSTR szFileName, LPCWSTR szNewFileName, const MMIOINFO *lpmmioinfo, DWORD dwFlags)
Definition: mmio.c:1319
static DWORD CALLBACK MCI_SCAStarter(LPVOID arg)
Definition: mciwave.c:82
DWORD dwMciTimeFormat
Definition: mciwave.c:52
DWORD nSamplesPerSec
Definition: mmreg.h:80
UINT WINAPI waveOutRestart(HWAVEOUT hWaveOut)
Definition: winmm.c:2402
WORD nBlockAlign
Definition: mmreg.h:82
#define MCIERR_UNRECOGNIZED_COMMAND
Definition: mmsystem.h:571
#define HRESULT_CODE(hr)
Definition: winerror.h:76
DWORD_PTR dwCallback
Definition: mmsystem.h:1639
#define MCIERR_HARDWARE
Definition: mmsystem.h:572
#define MCI_GETDEVCAPS_CAN_EJECT
Definition: mmsystem.h:765
WORD wBitsPerSample
Definition: mmreg.h:83
#define MCI_MODE_PAUSE
Definition: mmsystem.h:699
#define MCI_PAUSE
Definition: mmsystem.h:652
#define MCI_FROM
Definition: mmsystem.h:731
#define WHDR_DONE
Definition: mmsystem.h:193
#define MCIERR_DEVICE_OPEN
Definition: mmsystem.h:575
static DWORD WAVE_mciInfo(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_INFO_PARMSW lpParms)
Definition: mciwave.c:1670
#define DRV_INSTALL
Definition: mmsystem.h:127
LRESULT WINAPI DefDriverProc(DWORD_PTR dwDriverIdentifier, HDRVR hDrv, UINT Msg, LPARAM lParam1, LPARAM lParam2)
Definition: driver.c:554
static DWORD WAVE_ConvertTimeFormatToByte(WINE_MCIWAVE *wmw, DWORD val)
Definition: mciwave.c:251
#define WIM_DATA
Definition: mmsystem.h:186
#define MCI_DEVTYPE_WAVEFORM_AUDIO
Definition: mmsystem.h:689
#define MMIO_CREATE
Definition: mmsystem.h:528
UINT WINAPI waveInGetNumDevs(void)
Definition: winmm.c:2568
#define WAVE_ALIGN_ON_BLOCK(wmw, v)
int nUseCount
Definition: mciwave.c:41
#define MCIERR_INVALID_DEVICE_ID
Definition: mmsystem.h:569
#define MCI_SET_AUDIO_ALL
Definition: mmsystem.h:779
#define MCI_FORMAT_BYTES
Definition: mmsystem.h:709
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define MCI_STATUS_TIME_FORMAT
Definition: mmsystem.h:749
LONG_PTR LRESULT
Definition: windef.h:209
#define MCI_NOTIFY
Definition: mmsystem.h:729
#define INFINITE
Definition: serial.h:102
void cleanUp()
Definition: main.cpp:472
#define MCI_WAVE_GETDEVCAPS_OUTPUTS
Definition: mmsystem.h:840
#define MCI_STATUS_MEDIA_PRESENT
Definition: mmsystem.h:748
#define MCIERR_NULL_PARAMETER_BLOCK
Definition: mmsystem.h:605
LONG dwEventCount
Definition: mciwave.c:55
#define MCI_SPIN
Definition: mmsystem.h:655
UINT WINAPI waveOutReset(HWAVEOUT hWaveOut)
Definition: winmm.c:2388
#define LOWORD(l)
Definition: pedump.c:82
#define HeapFree(x, y, z)
Definition: compat.h:403
#define MCI_UPDATE
Definition: mmsystem.h:674
#define MulDiv(x, y, z)
Definition: gdifloat.h:86
#define MCI_SEEK
Definition: mmsystem.h:650
#define MCI_DELETE
Definition: mmsystem.h:676
#define MCI_TO
Definition: mmsystem.h:732
DWORD dwBytesRecorded
Definition: mmsystem.h:1016
#define MCI_WAVE_SET_BLOCKALIGN
Definition: mmsystem.h:826
LONG WINAPI mmioRead(HMMIO hmmio, HPSTR pch, LONG cch)
Definition: mmio.c:732
#define MCI_SET_DOOR_OPEN
Definition: mmsystem.h:772
#define MCI_FORMAT_RETURN_BASE
Definition: mmddk.h:343
#define MCI_STATUS_READY
Definition: mmsystem.h:750
static DWORD WAVE_mciClose(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
Definition: mciwave.c:660
#define MCI_GETDEVCAPS_CAN_PLAY
Definition: mmsystem.h:766
static DWORD WAVE_mciSet(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_WAVE_SET_PARMS lpParms)
Definition: mciwave.c:1293