ReactOS  0.4.14-dev-57-g333b8f1
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 #include "wine/unicode.h"
36 
38 
39 typedef struct {
42  int nUseCount; /* Incremented for each shared open */
43  HMMIO hFile; /* mmio file handle open as Element */
44  MCIDEVICEID wNotifyDeviceID; /* MCI device ID with a pending notification */
45  HANDLE hCallback; /* Callback handle for pending notification */
46  LPWSTR lpFileName; /* Name of file (if any) */
48  LPWAVEFORMATEX lpWaveFormat; /* Points to wfxRef until set by OPEN or RECORD */
49  BOOL fInput; /* FALSE = Output, TRUE = Input */
50  WORD wInput; /* wave input device */
51  WORD wOutput; /* wave output device */
52  volatile WORD dwStatus; /* one from MCI_MODE_xxxx */
53  DWORD dwMciTimeFormat;/* One of the supported MCI_FORMAT_xxxx */
54  DWORD dwPosition; /* position in bytes in chunk */
55  HANDLE hEvent; /* for synchronization */
56  LONG dwEventCount; /* for synchronization */
57  MMCKINFO ckMainRIFF; /* main RIFF chunk */
58  MMCKINFO ckWaveData; /* data chunk */
59 } WINE_MCIWAVE;
60 
61 /* ===================================================================
62  * ===================================================================
63  * FIXME: should be using the new mmThreadXXXX functions from WINMM
64  * instead of those
65  * it would require to add a wine internal flag to mmThreadCreate
66  * in order to pass a 32 bit function instead of a 16 bit one
67  * ===================================================================
68  * =================================================================== */
69 
71 
72 struct SCA {
78 };
79 
80 /**************************************************************************
81  * MCI_SCAStarter [internal]
82  */
84 {
85  struct SCA* sca = (struct SCA*)arg;
86  DWORD ret;
87 
88  TRACE("In thread before async command (%08x,%08lx,%08lx)\n",
89  sca->wDevID, sca->dwParam1, sca->dwParam2);
90  ret = sca->cmd(sca->wDevID, sca->dwParam1 | MCI_WAIT, sca->dwParam2, sca->evt);
91  TRACE("In thread after async command (%08x,%08lx,%08lx)\n",
92  sca->wDevID, sca->dwParam1, sca->dwParam2);
93  HeapFree(GetProcessHeap(), 0, sca);
94  return ret;
95 }
96 
97 /**************************************************************************
98  * MCI_SendCommandAsync [internal]
99  */
102 {
103  HANDLE handles[2];
104  struct SCA* sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA) + size);
105 
106  if (sca == 0)
107  return MCIERR_OUT_OF_MEMORY;
108 
109  sca->wDevID = wDevID;
110  sca->cmd = cmd;
111  sca->dwParam1 = dwParam1;
112 
113  if (size && dwParam2) {
114  sca->dwParam2 = (DWORD_PTR)sca + sizeof(struct SCA);
115  /* copy structure passed by program in dwParam2 to be sure
116  * we can still use it whatever the program does
117  */
119  } else {
120  sca->dwParam2 = dwParam2;
121  }
122 
123  if ((sca->evt = handles[1] = CreateEventW(NULL, FALSE, FALSE, NULL)) == NULL ||
124  (handles[0] = CreateThread(NULL, 0, MCI_SCAStarter, sca, 0, NULL)) == 0) {
125  WARN("Couldn't allocate thread for async command handling, sending synchronously\n");
126  if (handles[1]) CloseHandle(handles[1]);
127  sca->evt = NULL;
128  return MCI_SCAStarter(&sca);
129  }
130 
132  /* wait until either:
133  * - the thread has finished (handles[0], likely an error)
134  * - init phase of async command is done (handles[1])
135  */
137  CloseHandle(handles[0]);
138  CloseHandle(handles[1]);
139  return 0;
140 }
141 
142 /*======================================================================*
143  * MCI WAVE implementation *
144  *======================================================================*/
145 
147 
148 /**************************************************************************
149  * MCIWAVE_drvOpen [internal]
150  */
152 {
153  WINE_MCIWAVE* wmw;
154 
155  if (modp == NULL) return 0xFFFFFFFF;
156 
158 
159  if (!wmw)
160  return 0;
161 
162  wmw->wDevID = modp->wDeviceID;
163  mciSetDriverData(wmw->wDevID, (DWORD_PTR)wmw);
166 
167  wmw->wfxRef.wFormatTag = WAVE_FORMAT_PCM;
168  wmw->wfxRef.nChannels = 1; /* MONO */
169  wmw->wfxRef.nSamplesPerSec = 11025;
170  wmw->wfxRef.nAvgBytesPerSec = 11025;
171  wmw->wfxRef.nBlockAlign = 1;
172  wmw->wfxRef.wBitsPerSample = 8;
173  wmw->wfxRef.cbSize = 0; /* don't care */
174 
175  return modp->wDeviceID;
176 }
177 
178 /**************************************************************************
179  * MCIWAVE_drvClose [internal]
180  */
182 {
183  WINE_MCIWAVE* wmw = (WINE_MCIWAVE*)mciGetDriverData(dwDevID);
184 
185  if (wmw) {
186  HeapFree(GetProcessHeap(), 0, wmw);
187  mciSetDriverData(dwDevID, 0);
188  return 1;
189  }
190  return (dwDevID == 0xFFFFFFFF) ? 1 : 0;
191 }
192 
193 /**************************************************************************
194  * WAVE_mciGetOpenDev [internal]
195  */
197 {
199 
200  if (wmw == NULL || wmw->nUseCount == 0) {
201  WARN("Invalid wDevID=%u\n", wDevID);
202  return 0;
203  }
204  return wmw;
205 }
206 
207 /**************************************************************************
208  * WAVE_mciNotify [internal]
209  *
210  * Notifications in MCI work like a 1-element queue.
211  * Each new notification request supersedes the previous one.
212  * This affects Play and Record; other commands are immediate.
213  */
214 static void WAVE_mciNotify(DWORD_PTR hWndCallBack, WINE_MCIWAVE* wmw, UINT wStatus)
215 {
216  /* We simply save one parameter by not passing the wDevID local
217  * to the command. They are the same (via mciGetDriverData).
218  */
222  mciDriverNotify(HWND_32(LOWORD(hWndCallBack)), wDevID, wStatus);
223 }
224 
225 /**************************************************************************
226  * WAVE_ConvertByteToTimeFormat [internal]
227  */
229 {
230  DWORD ret = 0;
231 
232  switch (wmw->dwMciTimeFormat) {
234  ret = MulDiv(val,1000,wmw->lpWaveFormat->nAvgBytesPerSec);
235  break;
236  case MCI_FORMAT_BYTES:
237  ret = val;
238  break;
239  case MCI_FORMAT_SAMPLES:
241  break;
242  default:
243  WARN("Bad time format %u!\n", wmw->dwMciTimeFormat);
244  }
245  TRACE("val=%u=0x%08x [tf=%u] => ret=%u\n", val, val, wmw->dwMciTimeFormat, ret);
246  return ret;
247 }
248 
249 /**************************************************************************
250  * WAVE_ConvertTimeFormatToByte [internal]
251  */
253 {
254  DWORD ret = 0;
255 
256  switch (wmw->dwMciTimeFormat) {
258  ret = MulDiv(val,wmw->lpWaveFormat->nAvgBytesPerSec,1000);
259  if (ret > wmw->ckWaveData.cksize &&
261  ret = wmw->ckWaveData.cksize;
262  break;
263  case MCI_FORMAT_BYTES:
264  ret = val;
265  break;
266  case MCI_FORMAT_SAMPLES:
268  break;
269  default:
270  WARN("Bad time format %u!\n", wmw->dwMciTimeFormat);
271  }
272  TRACE("val=%u=0x%08x [tf=%u] => ret=%u\n", val, val, wmw->dwMciTimeFormat, ret);
273  return ret;
274 }
275 
276 /**************************************************************************
277  * WAVE_mciReadFmt [internal]
278  */
279 static DWORD WAVE_mciReadFmt(WINE_MCIWAVE* wmw, const MMCKINFO* pckMainRIFF)
280 {
281  MMCKINFO mmckInfo;
282  LONG r;
283  LPWAVEFORMATEX pwfx;
284 
285  mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
286  if (mmioDescend(wmw->hFile, &mmckInfo, pckMainRIFF, MMIO_FINDCHUNK) != 0)
287  return MCIERR_INVALID_FILE;
288  TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08X\n",
289  (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType, mmckInfo.cksize);
290 
291  pwfx = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
292  if (!pwfx) return MCIERR_OUT_OF_MEMORY;
293 
294  r = mmioRead(wmw->hFile, (HPSTR)pwfx, mmckInfo.cksize);
295  if (r < sizeof(PCMWAVEFORMAT)) {
296  HeapFree(GetProcessHeap(), 0, pwfx);
297  return MCIERR_INVALID_FILE;
298  }
299  TRACE("wFormatTag=%04X !\n", pwfx->wFormatTag);
300  TRACE("nChannels=%d\n", pwfx->nChannels);
301  TRACE("nSamplesPerSec=%d\n", pwfx->nSamplesPerSec);
302  TRACE("nAvgBytesPerSec=%d\n", pwfx->nAvgBytesPerSec);
303  TRACE("nBlockAlign=%d\n", pwfx->nBlockAlign);
304  TRACE("wBitsPerSample=%u !\n", pwfx->wBitsPerSample);
305  if (r >= sizeof(WAVEFORMATEX))
306  TRACE("cbSize=%u !\n", pwfx->cbSize);
307  if ((pwfx->wFormatTag != WAVE_FORMAT_PCM)
308  && (r < sizeof(WAVEFORMATEX) || (r < sizeof(WAVEFORMATEX) + pwfx->cbSize))) {
309  HeapFree(GetProcessHeap(), 0, pwfx);
310  return MCIERR_INVALID_FILE;
311  }
312  wmw->lpWaveFormat = pwfx;
313 
314  mmioAscend(wmw->hFile, &mmckInfo, 0);
315  wmw->ckWaveData.ckid = mmioFOURCC('d', 'a', 't', 'a');
316  if (mmioDescend(wmw->hFile, &wmw->ckWaveData, pckMainRIFF, MMIO_FINDCHUNK) != 0) {
317  TRACE("can't find data chunk\n");
318  return MCIERR_INVALID_FILE;
319  }
320  TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08X\n",
322  return 0;
323 }
324 
325 /**************************************************************************
326  * WAVE_mciDefaultFmt [internal]
327  *
328  * wmw->lpWaveFormat points to the default wave format at wmw->wfxRef
329  * until either Open File or Record. It becomes immutable afterwards,
330  * i.e. Set wave format or channels etc. is subsequently refused.
331  */
333 {
334  wmw->lpWaveFormat = &wmw->wfxRef;
336  wmw->lpWaveFormat->nChannels = 1;
337  wmw->lpWaveFormat->nSamplesPerSec = 11025;
338  wmw->lpWaveFormat->nAvgBytesPerSec = 11025;
339  wmw->lpWaveFormat->nBlockAlign = 1;
340  wmw->lpWaveFormat->wBitsPerSample = 8;
341  wmw->lpWaveFormat->cbSize = 0;
342 }
343 
344 /**************************************************************************
345  * WAVE_mciCreateRIFFSkeleton [internal]
346  */
348 {
349  MMCKINFO ckWaveFormat;
350  LPMMCKINFO lpckRIFF = &(wmw->ckMainRIFF);
351  LPMMCKINFO lpckWaveData = &(wmw->ckWaveData);
352 
353  lpckRIFF->ckid = FOURCC_RIFF;
354  lpckRIFF->fccType = mmioFOURCC('W', 'A', 'V', 'E');
355  lpckRIFF->cksize = 0;
356 
357  if (MMSYSERR_NOERROR != mmioCreateChunk(wmw->hFile, lpckRIFF, MMIO_CREATERIFF))
358  goto err;
359 
360  ckWaveFormat.fccType = 0;
361  ckWaveFormat.ckid = mmioFOURCC('f', 'm', 't', ' ');
362  ckWaveFormat.cksize = sizeof(PCMWAVEFORMAT);
363 
364  /* Set wave format accepts PCM only, however open an
365  * existing ADPCM file, record into it and the MCI will
366  * happily save back in that format. */
367  if (wmw->lpWaveFormat->wFormatTag == WAVE_FORMAT_PCM) {
368  if (wmw->lpWaveFormat->nBlockAlign !=
370  WORD size = wmw->lpWaveFormat->nChannels *
372  WARN("Incorrect nBlockAlign (%d), setting it to %d\n",
373  wmw->lpWaveFormat->nBlockAlign, size);
374  wmw->lpWaveFormat->nBlockAlign = size;
375  }
376  if (wmw->lpWaveFormat->nAvgBytesPerSec !=
378  DWORD speed = wmw->lpWaveFormat->nSamplesPerSec *
380  WARN("Incorrect nAvgBytesPerSec (%d), setting it to %d\n",
381  wmw->lpWaveFormat->nAvgBytesPerSec, speed);
382  wmw->lpWaveFormat->nAvgBytesPerSec = speed;
383  }
384  }
385  if (wmw->lpWaveFormat == &wmw->wfxRef) {
387  if (!pwfx) return MCIERR_OUT_OF_MEMORY;
388  /* Set wave format accepts PCM only so the size is known. */
390  *pwfx = wmw->wfxRef;
391  wmw->lpWaveFormat = pwfx;
392  }
393 
394  if (MMSYSERR_NOERROR != mmioCreateChunk(wmw->hFile, &ckWaveFormat, 0))
395  goto err;
396 
397  if (-1 == mmioWrite(wmw->hFile, (HPCSTR)wmw->lpWaveFormat, (WAVE_FORMAT_PCM==wmw->lpWaveFormat->wFormatTag)
398  ? sizeof(PCMWAVEFORMAT) : sizeof(WAVEFORMATEX)+wmw->lpWaveFormat->cbSize))
399  goto err;
400 
401  if (MMSYSERR_NOERROR != mmioAscend(wmw->hFile, &ckWaveFormat, 0))
402  goto err;
403 
404  lpckWaveData->cksize = 0;
405  lpckWaveData->fccType = 0;
406  lpckWaveData->ckid = mmioFOURCC('d', 'a', 't', 'a');
407 
408  /* create data chunk */
409  if (MMSYSERR_NOERROR != mmioCreateChunk(wmw->hFile, lpckWaveData, 0))
410  goto err;
411 
412  return 0;
413 
414 err:
415  /* mciClose takes care of wmw->lpWaveFormat. */
416  return MCIERR_INVALID_FILE;
417 }
418 
419 static DWORD create_tmp_file(HMMIO* hFile, LPWSTR* pszTmpFileName)
420 {
421  WCHAR szTmpPath[MAX_PATH];
422  WCHAR szPrefix[4];
423  DWORD dwRet = MMSYSERR_NOERROR;
424 
425  szPrefix[0] = 'M';
426  szPrefix[1] = 'C';
427  szPrefix[2] = 'I';
428  szPrefix[3] = '\0';
429 
430  if (!GetTempPathW(ARRAY_SIZE(szTmpPath), szTmpPath)) {
431  WARN("can't retrieve temp path!\n");
432  *pszTmpFileName = NULL;
433  return MCIERR_FILE_NOT_FOUND;
434  }
435 
436  *pszTmpFileName = HeapAlloc(GetProcessHeap(),
438  MAX_PATH * sizeof(WCHAR));
439  if (!GetTempFileNameW(szTmpPath, szPrefix, 0, *pszTmpFileName)) {
440  WARN("can't retrieve temp file name!\n");
441  HeapFree(GetProcessHeap(), 0, *pszTmpFileName);
442  return MCIERR_FILE_NOT_FOUND;
443  }
444 
445  TRACE("%s!\n", debugstr_w(*pszTmpFileName));
446 
447  if (*pszTmpFileName && (*pszTmpFileName)[0]) {
448 
449  *hFile = mmioOpenW(*pszTmpFileName, NULL,
451 
452  if (*hFile == 0) {
453  WARN("can't create file=%s!\n", debugstr_w(*pszTmpFileName));
454  /* temporary file could not be created. clean filename. */
455  HeapFree(GetProcessHeap(), 0, *pszTmpFileName);
456  dwRet = MCIERR_FILE_NOT_FOUND;
457  }
458  }
459  return dwRet;
460 }
461 
463 {
464  LRESULT dwRet = MMSYSERR_NOERROR;
465  LPWSTR fn;
466 
467  fn = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1) * sizeof(WCHAR));
468  if (!fn) return MCIERR_OUT_OF_MEMORY;
469  strcpyW(fn, filename);
470  HeapFree(GetProcessHeap(), 0, wmw->lpFileName);
471  wmw->lpFileName = fn;
472 
473  if (filename[0]) {
474  /* FIXME : what should be done if wmw->hFile is already != 0, or the driver is playin' */
475  TRACE("MCI_OPEN_ELEMENT %s!\n", debugstr_w(filename));
476 
479 
480  if (wmw->hFile == 0) {
481  WARN("can't find file=%s!\n", debugstr_w(filename));
482  dwRet = MCIERR_FILE_NOT_FOUND;
483  }
484  else
485  {
486  LPMMCKINFO lpckMainRIFF = &wmw->ckMainRIFF;
487 
488  /* make sure we're at the beginning of the file */
489  mmioSeek(wmw->hFile, 0, SEEK_SET);
490 
491  /* first reading of this file. read the waveformat chunk */
492  if (mmioDescend(wmw->hFile, lpckMainRIFF, NULL, 0) != 0) {
493  dwRet = MCIERR_INVALID_FILE;
494  } else {
495  TRACE("ParentChunk ckid=%.4s fccType=%.4s cksize=%08X\n",
496  (LPSTR)&(lpckMainRIFF->ckid),
497  (LPSTR) &(lpckMainRIFF->fccType),
498  (lpckMainRIFF->cksize));
499 
500  if ((lpckMainRIFF->ckid != FOURCC_RIFF) ||
501  lpckMainRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E')) {
502  dwRet = MCIERR_INVALID_FILE;
503  } else {
504  dwRet = WAVE_mciReadFmt(wmw, lpckMainRIFF);
505  }
506  }
507  }
508  }
509  return dwRet;
510 }
511 
512 /**************************************************************************
513  * WAVE_mciOpen [internal]
514  */
516 {
517  DWORD dwRet = 0;
519 
520  TRACE("(%04X, %08X, %p)\n", wDevID, dwFlags, lpOpenParms);
521  if (lpOpenParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
522  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
523 
526 
527  if (wmw->nUseCount > 0) {
528  /* The driver is already opened on this channel
529  * Wave driver cannot be shared
530  */
531  return MCIERR_DEVICE_OPEN;
532  }
533 
534  wmw->nUseCount++;
535 
536  wmw->wInput = wmw->wOutput = WAVE_MAPPER;
537  wmw->fInput = FALSE;
538  wmw->hWave = 0;
540  wmw->hFile = 0;
541  wmw->lpFileName = NULL; /* will be set by WAVE_mciOpenFile */
542  wmw->hCallback = NULL;
543  WAVE_mciDefaultFmt(wmw);
544 
545  TRACE("wDevID=%04X (lpParams->wDeviceID=%08X)\n", wDevID, lpOpenParms->wDeviceID);
546  /* Logs show the native winmm calls us with 0 still in lpOpenParms.wDeviceID */
547  wmw->wNotifyDeviceID = wDevID;
548 
549  if (dwFlags & MCI_OPEN_ELEMENT) {
551  /* could it be that (DWORD)lpOpenParms->lpstrElementName
552  * contains the hFile value ?
553  */
555  } else {
556  dwRet = WAVE_mciOpenFile(wmw, lpOpenParms->lpstrElementName);
557  }
558  }
559  TRACE("hFile=%p\n", wmw->hFile);
560 
561  if (dwRet == 0) {
562  wmw->dwPosition = 0;
563 
564  wmw->dwStatus = MCI_MODE_STOP;
565 
566  if (dwFlags & MCI_NOTIFY)
567  WAVE_mciNotify(lpOpenParms->dwCallback, wmw, MCI_NOTIFY_SUCCESSFUL);
568  } else {
569  wmw->nUseCount--;
570  if (wmw->hFile != 0)
571  mmioClose(wmw->hFile, 0);
572  wmw->hFile = 0;
573  HeapFree(GetProcessHeap(), 0, wmw->lpFileName);
574  wmw->lpFileName = NULL;
575  }
576  return dwRet;
577 }
578 
579 /**************************************************************************
580  * WAVE_mciCue [internal]
581  */
583 {
585 
586  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
587 
588  /* Tests on systems without sound drivers show that Cue, like
589  * Record and Play, opens winmm, returning MCIERR_WAVE_xyPUTSUNSUITABLE.
590  * The first Cue Notify does not immediately return the
591  * notification, as if a player or recorder thread is started.
592  * PAUSE mode is reported when successful, but this mode is
593  * different from the normal Pause, because a) Pause then returns
594  * NONAPPLICABLE_FUNCTION instead of 0 and b) Set Channels etc. is
595  * still accepted, returning the original notification as ABORTED.
596  * I.e. Cue allows subsequent format changes, unlike Record or
597  * Open file, closes winmm if the format changes and stops this
598  * thread.
599  * Wine creates one player or recorder thread per async. Play or
600  * Record command. Notification behaviour suggests that MS-W*
601  * reuses a single thread to improve response times. Having Cue
602  * start this thread early helps to improve Play/Record's initial
603  * response time. In effect, Cue is a performance hint, which
604  * justifies our almost no-op implementation.
605  */
606 
607  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
609 
610  if ((dwFlags & MCI_NOTIFY) && lpParms)
612 
613  return MMSYSERR_NOERROR;
614 }
615 
616 /**************************************************************************
617  * WAVE_mciStop [internal]
618  */
620 {
621  DWORD dwRet = 0;
623 
624  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
625 
626  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
627 
628  if (wmw->dwStatus != MCI_MODE_STOP) {
630  if (old) mciDriverNotify(old, wDevID, MCI_NOTIFY_ABORTED);
631  }
632 
633  /* wait for playback thread (if any) to exit before processing further */
634  switch (wmw->dwStatus) {
635  case MCI_MODE_PAUSE:
636  case MCI_MODE_PLAY:
637  case MCI_MODE_RECORD:
638  {
639  int oldStat = wmw->dwStatus;
641  if (oldStat == MCI_MODE_PAUSE)
642  dwRet = (wmw->fInput) ? waveInReset(wmw->hWave) : waveOutReset(wmw->hWave);
643  }
644  while (wmw->dwStatus != MCI_MODE_STOP)
645  Sleep(10);
646  break;
647  }
648 
649  /* sanity resets */
650  wmw->dwStatus = MCI_MODE_STOP;
651 
652  if ((dwFlags & MCI_NOTIFY) && lpParms && MMSYSERR_NOERROR==dwRet)
654 
655  return dwRet;
656 }
657 
658 /**************************************************************************
659  * WAVE_mciClose [internal]
660  */
662 {
663  DWORD dwRet = 0;
665 
666  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
667 
668  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
669 
670  if (wmw->dwStatus != MCI_MODE_STOP) {
671  /* mciStop handles MCI_NOTIFY_ABORTED */
672  dwRet = WAVE_mciStop(wDevID, MCI_WAIT, lpParms);
673  }
674 
675  wmw->nUseCount--;
676 
677  if (wmw->nUseCount == 0) {
678  if (wmw->hFile != 0) {
679  mmioClose(wmw->hFile, 0);
680  wmw->hFile = 0;
681  }
682  }
683 
684  if (wmw->lpWaveFormat != &wmw->wfxRef)
686  wmw->lpWaveFormat = &wmw->wfxRef;
687  HeapFree(GetProcessHeap(), 0, wmw->lpFileName);
688  wmw->lpFileName = NULL;
689 
690  if ((dwFlags & MCI_NOTIFY) && lpParms) {
691  WAVE_mciNotify(lpParms->dwCallback, wmw,
692  (dwRet == 0) ? MCI_NOTIFY_SUCCESSFUL : MCI_NOTIFY_FAILURE);
693  }
694 
695  return 0;
696 }
697 
698 /**************************************************************************
699  * WAVE_mciPlayCallback [internal]
700  */
701 static void CALLBACK WAVE_mciPlayCallback(HWAVEOUT hwo, UINT uMsg,
702  DWORD_PTR dwInstance,
704 {
705  WINE_MCIWAVE* wmw = (WINE_MCIWAVE*)dwInstance;
706 
707  switch (uMsg) {
708  case WOM_OPEN:
709  case WOM_CLOSE:
710  break;
711  case WOM_DONE:
713  TRACE("Returning waveHdr=%lx\n", dwParam1);
714  SetEvent(wmw->hEvent);
715  break;
716  default:
717  ERR("Unknown uMsg=%d\n", uMsg);
718  }
719 }
720 
721 /******************************************************************
722  * WAVE_mciPlayWaitDone [internal]
723  */
725 {
726  for (;;) {
727  ResetEvent(wmw->hEvent);
728  if (InterlockedDecrement(&wmw->dwEventCount) >= 0) {
729  break;
730  }
732 
734  }
735 }
736 
737 /**************************************************************************
738  * WAVE_mciPlay [internal]
739  */
741 {
742  LPMCI_PLAY_PARMS lpParms = (void*)pmt;
743  DWORD end;
745  DWORD dwRet;
746  LPWAVEHDR waveHdr = NULL;
748  HANDLE oldcb;
749  int whidx;
750 
751  TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
752 
753  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
754  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
755 
756  if (wmw->hFile == 0) {
757  WARN("Can't play: no file=%s!\n", debugstr_w(wmw->lpFileName));
758  return MCIERR_FILE_NOT_FOUND;
759  }
760 
761  if (wmw->dwStatus == MCI_MODE_PAUSE && !wmw->fInput && !(dwFlags & (MCI_FROM | MCI_TO))) {
762  /* FIXME: notification is different with Resume than Play */
764  }
765 
770  if ( !(wmw->dwStatus == MCI_MODE_STOP) &&
771  !((wmw->dwStatus == MCI_MODE_PLAY) && (dwFlags & MCI_WAIT) && !wmw->hWave)) {
772  /* FIXME: Check FROM/TO parameters first. */
773  /* FIXME: Play; Play [notify|wait] must hook into the running player. */
774  dwRet = WAVE_mciStop(wDevID, MCI_WAIT, NULL);
775  if (dwRet) return dwRet;
776  }
777 
778  if (wmw->lpWaveFormat->wFormatTag == WAVE_FORMAT_PCM) {
779  if (wmw->lpWaveFormat->nBlockAlign !=
781  WARN("Incorrect nBlockAlign (%d), setting it to %d\n",
783  wmw->lpWaveFormat->nChannels *
784  wmw->lpWaveFormat->wBitsPerSample/8);
785  wmw->lpWaveFormat->nBlockAlign =
786  wmw->lpWaveFormat->nChannels *
788  }
789  if (wmw->lpWaveFormat->nAvgBytesPerSec !=
791  WARN("Incorrect nAvgBytesPerSec (%d), setting it to %d\n",
794  wmw->lpWaveFormat->nBlockAlign);
798  }
799  }
800 
801  end = wmw->ckWaveData.cksize;
802  if (dwFlags & MCI_TO) {
803  DWORD position = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwTo);
804  if (position > end) return MCIERR_OUTOFRANGE;
805  end = position;
806  }
807  if (dwFlags & MCI_FROM) {
808  DWORD position = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwFrom);
809  if (position > end) return MCIERR_OUTOFRANGE;
810  /* Seek rounds down, so do we. */
811  position /= wmw->lpWaveFormat->nBlockAlign;
812  position *= wmw->lpWaveFormat->nBlockAlign;
813  wmw->dwPosition = position;
814  }
815  if (end < wmw->dwPosition) return MCIERR_OUTOFRANGE;
816  left = end - wmw->dwPosition;
817  if (0==left) return MMSYSERR_NOERROR; /* FIXME: NOTIFY */
818 
819  wmw->fInput = FALSE; /* FIXME: waveInOpen may have been called. */
820  wmw->dwStatus = MCI_MODE_PLAY;
821 
822  if (!(dwFlags & MCI_WAIT)) {
824  (DWORD_PTR)lpParms, sizeof(MCI_PLAY_PARMS));
825  }
826 
827  TRACE("Playing from byte=%u to byte=%u\n", wmw->dwPosition, end);
828 
830  (dwFlags & MCI_NOTIFY) ? HWND_32(LOWORD(lpParms->dwCallback)) : NULL);
831  if (oldcb) mciDriverNotify(oldcb, wDevID, MCI_NOTIFY_ABORTED);
832  oldcb = NULL;
833 
834 #define WAVE_ALIGN_ON_BLOCK(wmw,v) \
835 ((((v) + (wmw)->lpWaveFormat->nBlockAlign - 1) / (wmw)->lpWaveFormat->nBlockAlign) * (wmw)->lpWaveFormat->nBlockAlign)
836 
837  /* go back to beginning of chunk plus the requested position */
838  /* FIXME: I'm not sure this is correct, notably because some data linked to
839  * the decompression state machine will not be correctly initialized.
840  * try it this way (other way would be to decompress from 0 up to dwPosition
841  * and to start sending to hWave when dwPosition is reached)
842  */
843  mmioSeek(wmw->hFile, wmw->ckWaveData.dwDataOffset + wmw->dwPosition, SEEK_SET); /* >= 0 */
844 
845  dwRet = waveOutOpen((HWAVEOUT *)&wmw->hWave, wmw->wOutput, wmw->lpWaveFormat,
847 
848  if (dwRet != 0) {
849  TRACE("Can't open low level audio device %d\n", dwRet);
850  dwRet = MCIERR_DEVICE_OPEN;
851  wmw->hWave = 0;
852  goto cleanUp;
853  }
854 
855  /* make it so that 3 buffers per second are needed */
856  bufsize = WAVE_ALIGN_ON_BLOCK(wmw, wmw->lpWaveFormat->nAvgBytesPerSec / 3);
857 
858  waveHdr = HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WAVEHDR) + 2 * bufsize);
859  waveHdr[0].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR);
860  waveHdr[1].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR) + bufsize;
861  waveHdr[0].dwUser = waveHdr[1].dwUser = 0L;
862  waveHdr[0].dwLoops = waveHdr[1].dwLoops = 0L;
863  waveHdr[0].dwFlags = waveHdr[1].dwFlags = 0L;
864  waveHdr[0].dwBufferLength = waveHdr[1].dwBufferLength = bufsize;
865  if (waveOutPrepareHeader(wmw->hWave, &waveHdr[0], sizeof(WAVEHDR)) ||
866  waveOutPrepareHeader(wmw->hWave, &waveHdr[1], sizeof(WAVEHDR))) {
867  dwRet = MCIERR_INTERNAL;
868  goto cleanUp;
869  }
870 
871  whidx = 0;
872  wmw->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
873  if (!wmw->hEvent) {
874  dwRet = MCIERR_OUT_OF_MEMORY;
875  goto cleanUp;
876  }
877  wmw->dwEventCount = 1L; /* for first buffer */
878 
879  TRACE("Playing (normalized) from byte=%u for %u bytes\n", wmw->dwPosition, left);
880  if (hEvent) SetEvent(hEvent);
881 
882  /* FIXME: this doesn't work if wmw->dwPosition != 0 */
883  while (left > 0 && wmw->dwStatus != MCI_MODE_STOP && wmw->dwStatus != MCI_MODE_NOT_READY) {
884  count = mmioRead(wmw->hFile, waveHdr[whidx].lpData, min(bufsize, left));
885  TRACE("mmioRead bufsize=%d count=%d\n", bufsize, count);
886  if (count < 1)
887  break;
888  /* count is always <= bufsize, so this is correct regarding the
889  * waveOutPrepareHeader function
890  */
891  waveHdr[whidx].dwBufferLength = count;
892  waveHdr[whidx].dwFlags &= ~WHDR_DONE;
893  TRACE("before WODM_WRITE lpWaveHdr=%p dwBufferLength=%u\n",
894  &waveHdr[whidx], waveHdr[whidx].dwBufferLength);
895  dwRet = waveOutWrite(wmw->hWave, &waveHdr[whidx], sizeof(WAVEHDR));
896  if (dwRet) {
897  ERR("Aborting play loop, WODM_WRITE error %d\n", dwRet);
898  dwRet = MCIERR_HARDWARE;
899  break;
900  }
901  left -= count;
902  wmw->dwPosition += count;
903  TRACE("after WODM_WRITE dwPosition=%u\n", wmw->dwPosition);
904  /* InterlockedDecrement if and only if waveOutWrite is successful */
906  whidx ^= 1;
907  }
908 
909  WAVE_mciPlayWaitDone(wmw); /* to balance first buffer */
910 
911  /* just to get rid of some race conditions between play, stop and pause */
912  waveOutReset(wmw->hWave);
913 
914  waveOutUnprepareHeader(wmw->hWave, &waveHdr[0], sizeof(WAVEHDR));
915  waveOutUnprepareHeader(wmw->hWave, &waveHdr[1], sizeof(WAVEHDR));
916 
917 cleanUp:
918  if (dwFlags & MCI_NOTIFY)
919  oldcb = InterlockedExchangePointer(&wmw->hCallback, NULL);
920 
921  HeapFree(GetProcessHeap(), 0, waveHdr);
922 
923  if (wmw->hWave) {
924  waveOutClose(wmw->hWave);
925  wmw->hWave = 0;
926  }
927  CloseHandle(wmw->hEvent);
928  wmw->hEvent = NULL;
929 
930  wmw->dwStatus = MCI_MODE_STOP;
931 
932  /* Let the potentially asynchronous commands support FAILURE notification. */
933  if (oldcb) mciDriverNotify(oldcb, wDevID,
935 
936  return dwRet;
937 }
938 
939 /**************************************************************************
940  * WAVE_mciRecordCallback [internal]
941  */
942 static void CALLBACK WAVE_mciRecordCallback(HWAVEOUT hwo, UINT uMsg,
943  DWORD_PTR dwInstance,
945 {
946  WINE_MCIWAVE* wmw = (WINE_MCIWAVE*)dwInstance;
947  LPWAVEHDR lpWaveHdr;
948  LONG count = 0;
949 
950  switch (uMsg) {
951  case WIM_OPEN:
952  case WIM_CLOSE:
953  break;
954  case WIM_DATA:
955  lpWaveHdr = (LPWAVEHDR) dwParam1;
956 
958 
959  count = mmioWrite(wmw->hFile, lpWaveHdr->lpData, lpWaveHdr->dwBytesRecorded);
960 
961  lpWaveHdr->dwFlags &= ~WHDR_DONE;
962  if (count > 0)
963  wmw->dwPosition += count;
964  /* else error reporting ?? */
965  if (wmw->dwStatus == MCI_MODE_RECORD)
966  {
967  /* Only queue up another buffer if we are recording. We could receive this
968  message also when waveInReset() is called, since it notifies on all wave
969  buffers that are outstanding. Queueing up more sometimes causes waveInClose
970  to fail. */
971  waveInAddBuffer(wmw->hWave, lpWaveHdr, sizeof(*lpWaveHdr));
972  TRACE("after mmioWrite dwPosition=%u\n", wmw->dwPosition);
973  }
974 
975  SetEvent(wmw->hEvent);
976  break;
977  default:
978  ERR("Unknown uMsg=%d\n", uMsg);
979  }
980 }
981 
982 /******************************************************************
983  * WAVE_mciRecordWaitDone [internal]
984  */
986 {
987  for (;;) {
988  ResetEvent(wmw->hEvent);
989  if (InterlockedDecrement(&wmw->dwEventCount) >= 0) {
990  break;
991  }
993 
995  }
996 }
997 
998 /**************************************************************************
999  * WAVE_mciRecord [internal]
1000  */
1002 {
1003  LPMCI_RECORD_PARMS lpParms = (void*)pmt;
1004  DWORD end;
1005  DWORD dwRet = MMSYSERR_NOERROR;
1006  LONG bufsize;
1007  LPWAVEHDR waveHdr = NULL;
1009  HANDLE oldcb;
1010 
1011  TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
1012 
1013  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1014  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1015 
1016  if (wmw->dwStatus == MCI_MODE_PAUSE && wmw->fInput) {
1017  /* FIXME: parameters (start/end) in lpParams may not be used */
1018  return WAVE_mciResume(wDevID, dwFlags, (LPMCI_GENERIC_PARMS)lpParms);
1019  }
1020 
1025  if ( !(wmw->dwStatus == MCI_MODE_STOP) &&
1026  !((wmw->dwStatus == MCI_MODE_RECORD) && (dwFlags & MCI_WAIT) && !wmw->hWave)) {
1027  return MCIERR_INTERNAL;
1028  }
1029 
1030  wmw->fInput = TRUE; /* FIXME: waveOutOpen may have been called. */
1031  wmw->dwStatus = MCI_MODE_RECORD;
1032 
1033  if (!(dwFlags & MCI_WAIT)) {
1035  (DWORD_PTR)lpParms, sizeof(MCI_RECORD_PARMS));
1036  }
1037 
1038  /* FIXME: we only re-create the RIFF structure from an existing file (if any)
1039  * we don't modify the wave part of an existing file (ie. we always erase an
1040  * existing content, we don't overwrite)
1041  */
1042  HeapFree(GetProcessHeap(), 0, wmw->lpFileName);
1043  dwRet = create_tmp_file(&wmw->hFile, (WCHAR**)&wmw->lpFileName);
1044  if (dwRet != 0) return dwRet;
1045 
1046  /* new RIFF file, lpWaveFormat now valid */
1047  dwRet = WAVE_mciCreateRIFFSkeleton(wmw);
1048  if (dwRet != 0) return dwRet;
1049 
1050  if (dwFlags & MCI_TO) {
1051  end = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwTo);
1052  } else end = 0xFFFFFFFF;
1053  if (dwFlags & MCI_FROM) {
1054  DWORD position = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwFrom);
1055  if (wmw->ckWaveData.cksize < position) return MCIERR_OUTOFRANGE;
1056  /* Seek rounds down, so do we. */
1057  position /= wmw->lpWaveFormat->nBlockAlign;
1058  position *= wmw->lpWaveFormat->nBlockAlign;
1059  wmw->dwPosition = position;
1060  }
1061  if (end==wmw->dwPosition) return MMSYSERR_NOERROR; /* FIXME: NOTIFY */
1062 
1063  TRACE("Recording from byte=%u to byte=%u\n", wmw->dwPosition, end);
1064 
1065  oldcb = InterlockedExchangePointer(&wmw->hCallback,
1066  (dwFlags & MCI_NOTIFY) ? HWND_32(LOWORD(lpParms->dwCallback)) : NULL);
1067  if (oldcb) mciDriverNotify(oldcb, wDevID, MCI_NOTIFY_ABORTED);
1068  oldcb = NULL;
1069 
1070 #define WAVE_ALIGN_ON_BLOCK(wmw,v) \
1071 ((((v) + (wmw)->lpWaveFormat->nBlockAlign - 1) / (wmw)->lpWaveFormat->nBlockAlign) * (wmw)->lpWaveFormat->nBlockAlign)
1072 
1074 
1075  /* Go back to the beginning of the chunk plus the requested position */
1076  /* FIXME: I'm not sure this is correct, notably because some data linked to
1077  * the decompression state machine will not be correctly initialized.
1078  * Try it this way (other way would be to decompress from 0 up to dwPosition
1079  * and to start sending to hWave when dwPosition is reached).
1080  */
1081  mmioSeek(wmw->hFile, wmw->ckWaveData.dwDataOffset + wmw->dwPosition, SEEK_SET); /* >= 0 */
1082 
1083  dwRet = waveInOpen((HWAVEIN*)&wmw->hWave, wmw->wInput, wmw->lpWaveFormat,
1085 
1086  if (dwRet != MMSYSERR_NOERROR) {
1087  TRACE("Can't open low level audio device %d\n", dwRet);
1088  dwRet = MCIERR_DEVICE_OPEN;
1089  wmw->hWave = 0;
1090  goto cleanUp;
1091  }
1092 
1093  /* make it so that 3 buffers per second are needed */
1094  bufsize = WAVE_ALIGN_ON_BLOCK(wmw, wmw->lpWaveFormat->nAvgBytesPerSec / 3);
1095 
1096  waveHdr = HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WAVEHDR) + 2 * bufsize);
1097  waveHdr[0].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR);
1098  waveHdr[1].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR) + bufsize;
1099  waveHdr[0].dwUser = waveHdr[1].dwUser = 0L;
1100  waveHdr[0].dwLoops = waveHdr[1].dwLoops = 0L;
1101  waveHdr[0].dwFlags = waveHdr[1].dwFlags = 0L;
1102  waveHdr[0].dwBufferLength = waveHdr[1].dwBufferLength = bufsize;
1103 
1104  if (waveInPrepareHeader(wmw->hWave, &waveHdr[0], sizeof(WAVEHDR)) ||
1105  waveInPrepareHeader(wmw->hWave, &waveHdr[1], sizeof(WAVEHDR))) {
1106  dwRet = MCIERR_INTERNAL;
1107  goto cleanUp;
1108  }
1109 
1110  if (waveInAddBuffer(wmw->hWave, &waveHdr[0], sizeof(WAVEHDR)) ||
1111  waveInAddBuffer(wmw->hWave, &waveHdr[1], sizeof(WAVEHDR))) {
1112  dwRet = MCIERR_INTERNAL;
1113  goto cleanUp;
1114  }
1115 
1116  wmw->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
1117  wmw->dwEventCount = 1L; /* for first buffer */
1118 
1119  TRACE("Recording (normalized) from byte=%u for %u bytes\n", wmw->dwPosition, end - wmw->dwPosition);
1120 
1121  waveInStart(wmw->hWave);
1122 
1123  if (hEvent) SetEvent(hEvent);
1124 
1125  while (wmw->dwPosition < end && wmw->dwStatus != MCI_MODE_STOP && wmw->dwStatus != MCI_MODE_NOT_READY) {
1127  }
1128  /* Grab callback before another thread kicks in after we change dwStatus. */
1129  if (dwFlags & MCI_NOTIFY) {
1130  oldcb = InterlockedExchangePointer(&wmw->hCallback, NULL);
1131  dwFlags &= ~MCI_NOTIFY;
1132  }
1133  /* needed so that the callback above won't add again the buffers returned by the reset */
1134  wmw->dwStatus = MCI_MODE_STOP;
1135 
1136  waveInReset(wmw->hWave);
1137 
1138  waveInUnprepareHeader(wmw->hWave, &waveHdr[0], sizeof(WAVEHDR));
1139  waveInUnprepareHeader(wmw->hWave, &waveHdr[1], sizeof(WAVEHDR));
1140 
1141  dwRet = 0;
1142 
1143 cleanUp:
1144  if (dwFlags & MCI_NOTIFY)
1145  oldcb = InterlockedExchangePointer(&wmw->hCallback, NULL);
1146 
1147  HeapFree(GetProcessHeap(), 0, waveHdr);
1148 
1149  if (wmw->hWave) {
1150  waveInClose(wmw->hWave);
1151  wmw->hWave = 0;
1152  }
1153  CloseHandle(wmw->hEvent);
1154 
1155  wmw->dwStatus = MCI_MODE_STOP;
1156 
1157  if (oldcb) mciDriverNotify(oldcb, wDevID,
1159 
1160  return dwRet;
1161 
1162 }
1163 
1164 /**************************************************************************
1165  * WAVE_mciPause [internal]
1166  */
1168 {
1169  DWORD dwRet;
1171 
1172  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
1173 
1174  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1175 
1176  switch (wmw->dwStatus) {
1177  case MCI_MODE_PLAY:
1178  dwRet = waveOutPause(wmw->hWave);
1179  if (dwRet==MMSYSERR_NOERROR) wmw->dwStatus = MCI_MODE_PAUSE;
1180  else { /* When playthread was not started yet, winmm not opened, error 5 MMSYSERR_INVALHANDLE */
1181  ERR("waveOutPause error %d\n",dwRet);
1182  dwRet = MCIERR_INTERNAL;
1183  }
1184  break;
1185  case MCI_MODE_RECORD:
1186  dwRet = waveInStop(wmw->hWave);
1187  if (dwRet==MMSYSERR_NOERROR) wmw->dwStatus = MCI_MODE_PAUSE;
1188  else {
1189  ERR("waveInStop error %d\n",dwRet);
1190  dwRet = MCIERR_INTERNAL;
1191  }
1192  break;
1193  case MCI_MODE_PAUSE:
1194  dwRet = MMSYSERR_NOERROR;
1195  break;
1196  default:
1198  }
1199  if (MMSYSERR_NOERROR==dwRet && (dwFlags & MCI_NOTIFY) && lpParms)
1201  return dwRet;
1202 }
1203 
1204 /**************************************************************************
1205  * WAVE_mciResume [internal]
1206  */
1208 {
1210  DWORD dwRet;
1211 
1212  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
1213 
1214  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1215 
1216  switch (wmw->dwStatus) {
1217  case MCI_MODE_PAUSE:
1218  /* Only update dwStatus if wave* succeeds and will exchange buffers buffers. */
1219  if (wmw->fInput) {
1220  dwRet = waveInStart(wmw->hWave);
1221  if (dwRet==MMSYSERR_NOERROR) wmw->dwStatus = MCI_MODE_RECORD;
1222  else {
1223  ERR("waveInStart error %d\n",dwRet);
1224  dwRet = MCIERR_INTERNAL;
1225  }
1226  } else {
1227  dwRet = waveOutRestart(wmw->hWave);
1228  if (dwRet==MMSYSERR_NOERROR) wmw->dwStatus = MCI_MODE_PLAY;
1229  else {
1230  ERR("waveOutRestart error %d\n",dwRet);
1231  dwRet = MCIERR_INTERNAL;
1232  }
1233  }
1234  break;
1235  case MCI_MODE_PLAY:
1236  case MCI_MODE_RECORD:
1237  dwRet = MMSYSERR_NOERROR;
1238  break;
1239  default:
1241  }
1242  if (MMSYSERR_NOERROR==dwRet && (dwFlags & MCI_NOTIFY) && lpParms)
1244  return dwRet;
1245 }
1246 
1247 /**************************************************************************
1248  * WAVE_mciSeek [internal]
1249  */
1251 {
1253  DWORD position, dwRet;
1254 
1255  TRACE("(%04X, %08X, %p);\n", wDevID, dwFlags, lpParms);
1256 
1257  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1258  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1259 
1261  if (!position) return MCIERR_MISSING_PARAMETER;
1262  if (position&(position-1)) return MCIERR_FLAGS_NOT_COMPATIBLE;
1263 
1264  /* Stop sends MCI_NOTIFY_ABORTED when needed */
1265  dwRet = WAVE_mciStop(wDevID, MCI_WAIT, 0);
1266  if (dwRet != MMSYSERR_NOERROR) return dwRet;
1267 
1268  if (dwFlags & MCI_TO) {
1269  position = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwTo);
1270  if (position > wmw->ckWaveData.cksize)
1271  return MCIERR_OUTOFRANGE;
1272  } else if (dwFlags & MCI_SEEK_TO_START) {
1273  position = 0;
1274  } else {
1275  position = wmw->ckWaveData.cksize;
1276  }
1277  /* Seek rounds down, unless at end */
1278  if (position != wmw->ckWaveData.cksize) {
1279  position /= wmw->lpWaveFormat->nBlockAlign;
1280  position *= wmw->lpWaveFormat->nBlockAlign;
1281  }
1282  wmw->dwPosition = position;
1283  TRACE("Seeking to position=%u bytes\n", position);
1284 
1285  if (dwFlags & MCI_NOTIFY)
1287 
1288  return MMSYSERR_NOERROR;
1289 }
1290 
1291 /**************************************************************************
1292  * WAVE_mciSet [internal]
1293  */
1295 {
1297 
1298  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
1299 
1300  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1301  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1302 
1303  if (dwFlags & MCI_SET_TIME_FORMAT) {
1304  switch (lpParms->dwTimeFormat) {
1306  TRACE("MCI_FORMAT_MILLISECONDS !\n");
1308  break;
1309  case MCI_FORMAT_BYTES:
1310  TRACE("MCI_FORMAT_BYTES !\n");
1312  break;
1313  case MCI_FORMAT_SAMPLES:
1314  TRACE("MCI_FORMAT_SAMPLES !\n");
1316  break;
1317  default:
1318  WARN("Bad time format %u!\n", lpParms->dwTimeFormat);
1319  return MCIERR_BAD_TIME_FORMAT;
1320  }
1321  }
1322  if (dwFlags & MCI_SET_VIDEO) {
1323  TRACE("No support for video !\n");
1325  }
1326  if (dwFlags & MCI_SET_DOOR_OPEN) {
1327  TRACE("No support for door open !\n");
1329  }
1330  if (dwFlags & MCI_SET_DOOR_CLOSED) {
1331  TRACE("No support for door close !\n");
1333  }
1334  if (dwFlags & MCI_SET_AUDIO) {
1335  if (dwFlags & MCI_SET_ON) {
1336  TRACE("MCI_SET_ON audio !\n");
1337  } else if (dwFlags & MCI_SET_OFF) {
1338  TRACE("MCI_SET_OFF audio !\n");
1339  } else {
1340  WARN("MCI_SET_AUDIO without SET_ON or SET_OFF\n");
1341  return MCIERR_BAD_INTEGER;
1342  }
1343 
1344  switch (lpParms->dwAudio)
1345  {
1346  case MCI_SET_AUDIO_ALL: TRACE("MCI_SET_AUDIO_ALL !\n"); break;
1347  case MCI_SET_AUDIO_LEFT: TRACE("MCI_SET_AUDIO_LEFT !\n"); break;
1348  case MCI_SET_AUDIO_RIGHT: TRACE("MCI_SET_AUDIO_RIGHT !\n"); break;
1349  default: WARN("Unknown audio channel %u\n", lpParms->dwAudio); break;
1350  }
1351  }
1352  if (dwFlags & MCI_WAVE_INPUT) {
1353  TRACE("MCI_WAVE_INPUT = %d\n", lpParms->wInput);
1354  if (lpParms->wInput >= waveInGetNumDevs())
1355  return MCIERR_OUTOFRANGE;
1356  if (wmw->wInput != (WORD)lpParms->wInput)
1358  wmw->wInput = lpParms->wInput;
1359  }
1360  if (dwFlags & MCI_WAVE_OUTPUT) {
1361  TRACE("MCI_WAVE_OUTPUT = %d\n", lpParms->wOutput);
1362  if (lpParms->wOutput >= waveOutGetNumDevs())
1363  return MCIERR_OUTOFRANGE;
1364  if (wmw->wOutput != (WORD)lpParms->wOutput)
1366  wmw->wOutput = lpParms->wOutput;
1367  }
1369  TRACE("MCI_WAVE_SET_ANYINPUT\n");
1370  if (wmw->wInput != (WORD)lpParms->wInput)
1372  wmw->wInput = WAVE_MAPPER;
1373  }
1375  TRACE("MCI_WAVE_SET_ANYOUTPUT\n");
1376  if (wmw->wOutput != (WORD)lpParms->wOutput)
1378  wmw->wOutput = WAVE_MAPPER;
1379  }
1380  /* Set wave format parameters is refused after Open or Record.*/
1382  TRACE("MCI_WAVE_SET_FORMATTAG = %d\n", lpParms->wFormatTag);
1383  if (wmw->lpWaveFormat != &wmw->wfxRef) return MCIERR_NONAPPLICABLE_FUNCTION;
1384  if (lpParms->wFormatTag != WAVE_FORMAT_PCM)
1385  return MCIERR_OUTOFRANGE;
1386  }
1388  if (wmw->lpWaveFormat != &wmw->wfxRef) return MCIERR_NONAPPLICABLE_FUNCTION;
1389  wmw->wfxRef.nAvgBytesPerSec = lpParms->nAvgBytesPerSec;
1390  TRACE("MCI_WAVE_SET_AVGBYTESPERSEC = %d\n", wmw->wfxRef.nAvgBytesPerSec);
1391  }
1393  if (wmw->lpWaveFormat != &wmw->wfxRef) return MCIERR_NONAPPLICABLE_FUNCTION;
1394  wmw->wfxRef.wBitsPerSample = lpParms->wBitsPerSample;
1395  TRACE("MCI_WAVE_SET_BITSPERSAMPLE = %d\n", wmw->wfxRef.wBitsPerSample);
1396  }
1398  if (wmw->lpWaveFormat != &wmw->wfxRef) return MCIERR_NONAPPLICABLE_FUNCTION;
1399  wmw->wfxRef.nBlockAlign = lpParms->nBlockAlign;
1400  TRACE("MCI_WAVE_SET_BLOCKALIGN = %d\n", wmw->wfxRef.nBlockAlign);
1401  }
1403  if (wmw->lpWaveFormat != &wmw->wfxRef) return MCIERR_NONAPPLICABLE_FUNCTION;
1404  wmw->wfxRef.nChannels = lpParms->nChannels;
1405  TRACE("MCI_WAVE_SET_CHANNELS = %d\n", wmw->wfxRef.nChannels);
1406  }
1408  if (wmw->lpWaveFormat != &wmw->wfxRef) return MCIERR_NONAPPLICABLE_FUNCTION;
1409  wmw->wfxRef.nSamplesPerSec = lpParms->nSamplesPerSec;
1410  TRACE("MCI_WAVE_SET_SAMPLESPERSEC = %d\n", wmw->wfxRef.nSamplesPerSec);
1411  }
1412  if (dwFlags & MCI_NOTIFY)
1414  return 0;
1415 }
1416 
1417 /**************************************************************************
1418  * WAVE_mciSave [internal]
1419  */
1421 {
1423  DWORD ret = MCIERR_FILE_NOT_SAVED, tmpRet;
1424 
1425  TRACE("%d, %08X, %p);\n", wDevID, dwFlags, lpParms);
1426  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1427  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1428 
1429  if (dwFlags & MCI_WAIT)
1430  {
1431  FIXME("MCI_WAIT not implemented\n");
1432  }
1433  WAVE_mciStop(wDevID, 0, NULL);
1434 
1435  ret = mmioAscend(wmw->hFile, &wmw->ckWaveData, 0);
1436  ret = mmioAscend(wmw->hFile, &wmw->ckMainRIFF, 0);
1437 
1438  ret = mmioClose(wmw->hFile, 0);
1439  wmw->hFile = 0;
1440 
1441  /*
1442  If the destination file already exists, it has to be overwritten. (Behaviour
1443  verified in Windows (2000)). If it doesn't overwrite, it is breaking one of
1444  my applications. We are making use of mmioRename, which WILL NOT overwrite
1445  the destination file (which is what Windows does, also verified in Win2K)
1446  So, lets delete the destination file before calling mmioRename. If the
1447  destination file DOESN'T exist, the delete will fail silently. Let's also be
1448  careful not to lose our previous error code.
1449  */
1450  tmpRet = GetLastError();
1451  DeleteFileW (lpParms->lpfilename);
1452  SetLastError(tmpRet);
1453 
1454  /* FIXME: Open file.wav; Save; must not rename the original file.
1455  * Nor must Save a.wav; Save b.wav rename a. */
1456  if (0 == mmioRenameW(wmw->lpFileName, lpParms->lpfilename, 0, 0 )) {
1458  }
1459 
1460  if (MMSYSERR_NOERROR==ret && (dwFlags & MCI_NOTIFY))
1462 
1463  if (ret == MMSYSERR_NOERROR)
1464  ret = WAVE_mciOpenFile(wmw, lpParms->lpfilename);
1465 
1466  return ret;
1467 }
1468 
1469 /**************************************************************************
1470  * WAVE_mciStatus [internal]
1471  */
1473 {
1475  DWORD ret = 0;
1476 
1477  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
1478  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1479  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1481 
1482  if (dwFlags & MCI_STATUS_ITEM) {
1483  switch (lpParms->dwItem) {
1485  lpParms->dwReturn = 1;
1486  TRACE("MCI_STATUS_CURRENT_TRACK => %lu\n", lpParms->dwReturn);
1487  break;
1488  case MCI_STATUS_LENGTH:
1489  if (!wmw->hFile) {
1490  lpParms->dwReturn = 0;
1492  }
1493  /* only one track in file is currently handled, so don't take care of MCI_TRACK flag */
1495  TRACE("MCI_STATUS_LENGTH => %lu\n", lpParms->dwReturn);
1496  break;
1497  case MCI_STATUS_MODE:
1498  TRACE("MCI_STATUS_MODE => %u\n", wmw->dwStatus);
1499  lpParms->dwReturn = MAKEMCIRESOURCE(wmw->dwStatus, wmw->dwStatus);
1501  break;
1503  TRACE("MCI_STATUS_MEDIA_PRESENT => TRUE!\n");
1504  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1506  break;
1508  /* only one track in file is currently handled, so don't take care of MCI_TRACK flag */
1509  lpParms->dwReturn = 1;
1510  TRACE("MCI_STATUS_NUMBER_OF_TRACKS => %lu\n", lpParms->dwReturn);
1511  break;
1512  case MCI_STATUS_POSITION:
1513  if (!wmw->hFile) {
1514  lpParms->dwReturn = 0;
1516  }
1517  /* only one track in file is currently handled, so don't take care of MCI_TRACK flag */
1518  lpParms->dwReturn = WAVE_ConvertByteToTimeFormat(wmw,
1519  (dwFlags & MCI_STATUS_START) ? 0 : wmw->dwPosition);
1520  TRACE("MCI_STATUS_POSITION %s => %lu\n",
1521  (dwFlags & MCI_STATUS_START) ? "start" : "current", lpParms->dwReturn);
1522  break;
1523  case MCI_STATUS_READY:
1524  lpParms->dwReturn = (wmw->dwStatus == MCI_MODE_NOT_READY) ?
1526  TRACE("MCI_STATUS_READY => %u!\n", LOWORD(lpParms->dwReturn));
1528  break;
1531  TRACE("MCI_STATUS_TIME_FORMAT => %lu\n", lpParms->dwReturn);
1533  break;
1534  case MCI_WAVE_INPUT:
1535  if (wmw->wInput != (WORD)WAVE_MAPPER)
1536  lpParms->dwReturn = wmw->wInput;
1537  else {
1540  }
1541  TRACE("MCI_WAVE_INPUT => %d\n", (signed)wmw->wInput);
1542  break;
1543  case MCI_WAVE_OUTPUT:
1544  if (wmw->wOutput != (WORD)WAVE_MAPPER)
1545  lpParms->dwReturn = wmw->wOutput;
1546  else {
1549  }
1550  TRACE("MCI_WAVE_OUTPUT => %d\n", (signed)wmw->wOutput);
1551  break;
1552  /* It is always ok to query wave format parameters,
1553  * except on auto-open yield MCIERR_UNSUPPORTED_FUNCTION. */
1556  lpParms->dwReturn = wmw->lpWaveFormat->wFormatTag;
1557  else {
1560  }
1561  TRACE("MCI_WAVE_FORMATTAG => %lu\n", lpParms->dwReturn);
1562  break;
1564  lpParms->dwReturn = wmw->lpWaveFormat->nAvgBytesPerSec;
1565  TRACE("MCI_WAVE_STATUS_AVGBYTESPERSEC => %lu\n", lpParms->dwReturn);
1566  break;
1568  lpParms->dwReturn = wmw->lpWaveFormat->wBitsPerSample;
1569  TRACE("MCI_WAVE_STATUS_BITSPERSAMPLE => %lu\n", lpParms->dwReturn);
1570  break;
1572  lpParms->dwReturn = wmw->lpWaveFormat->nBlockAlign;
1573  TRACE("MCI_WAVE_STATUS_BLOCKALIGN => %lu\n", lpParms->dwReturn);
1574  break;
1576  lpParms->dwReturn = wmw->lpWaveFormat->nChannels;
1577  TRACE("MCI_WAVE_STATUS_CHANNELS => %lu\n", lpParms->dwReturn);
1578  break;
1580  lpParms->dwReturn = wmw->lpWaveFormat->nSamplesPerSec;
1581  TRACE("MCI_WAVE_STATUS_SAMPLESPERSEC => %lu\n", lpParms->dwReturn);
1582  break;
1583  case MCI_WAVE_STATUS_LEVEL:
1584  TRACE("MCI_WAVE_STATUS_LEVEL !\n");
1585  lpParms->dwReturn = 0xAAAA5555;
1586  break;
1587  default:
1588  WARN("unknown command %08X !\n", lpParms->dwItem);
1590  }
1591  }
1592  if ((dwFlags & MCI_NOTIFY) && HRESULT_CODE(ret)==0)
1594  return ret;
1595 }
1596 
1597 /**************************************************************************
1598  * WAVE_mciGetDevCaps [internal]
1599  */
1601  LPMCI_GETDEVCAPS_PARMS lpParms)
1602 {
1604  DWORD ret = 0;
1605 
1606  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
1607 
1608  if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
1609  if (wmw == NULL) return MCIERR_INVALID_DEVICE_ID;
1610 
1611  if (dwFlags & MCI_GETDEVCAPS_ITEM) {
1612  switch(lpParms->dwItem) {
1616  break;
1618  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1620  break;
1622  lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
1624  break;
1626  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1628  break;
1630  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1632  break;
1634  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1636  break;
1638  lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
1640  break;
1642  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1644  break;
1646  lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
1648  break;
1650  lpParms->dwReturn = waveInGetNumDevs();
1651  break;
1653  lpParms->dwReturn = waveOutGetNumDevs();
1654  break;
1655  default:
1656  FIXME("Unknown capability (%08x) !\n", lpParms->dwItem);
1658  }
1659  } else {
1660  WARN("No GetDevCaps-Item !\n");
1662  }
1663  if ((dwFlags & MCI_NOTIFY) && HRESULT_CODE(ret)==0)
1665  return ret;
1666 }
1667 
1668 /**************************************************************************
1669  * WAVE_mciInfo [internal]
1670  */
1672 {
1673  DWORD ret = 0;
1674  LPCWSTR str = 0;
1676 
1677  TRACE("(%u, %08X, %p);\n", wDevID, dwFlags, lpParms);
1678 
1679  if (!lpParms || !lpParms->lpstrReturn)
1681 
1682  TRACE("buf=%p, len=%u\n", lpParms->lpstrReturn, lpParms->dwRetSize);
1683 
1684  if (wmw == NULL) {
1686  } else {
1687  static const WCHAR wszAudio [] = {'W','i','n','e','\'','s',' ','a','u','d','i','o',' ','p','l','a','y','e','r',0};
1688  static const WCHAR wszWaveIn [] = {'W','i','n','e',' ','W','a','v','e',' ','I','n',0};
1689  static const WCHAR wszWaveOut[] = {'W','i','n','e',' ','W','a','v','e',' ','O','u','t',0};
1690 
1691  switch (dwFlags & ~(MCI_WAIT|MCI_NOTIFY)) {
1692  case MCI_INFO_PRODUCT: str = wszAudio; break;
1693  case MCI_INFO_FILE: str = wmw->lpFileName; break;
1694  case MCI_WAVE_INPUT: str = wszWaveIn; break;
1695  case MCI_WAVE_OUTPUT: str = wszWaveOut; break;
1696  default:
1697  WARN("Don't know this info command (%u)\n", dwFlags);
1699  }
1700  }
1701  if (!ret) {
1702  if (lpParms->dwRetSize) {
1703  WCHAR zero = 0;
1704  /* FIXME? Since NT, mciwave, mciseq and mcicda set dwRetSize
1705  * to the number of characters written, excluding \0. */
1706  lstrcpynW(lpParms->lpstrReturn, str ? str : &zero, lpParms->dwRetSize);
1707  } else ret = MCIERR_PARAM_OVERFLOW;
1708  }
1709  if (MMSYSERR_NOERROR==ret && (dwFlags & MCI_NOTIFY))
1711  return ret;
1712 }
1713 
1714 /**************************************************************************
1715  * DriverProc (MCIWAVE.@)
1716  */
1717 LRESULT CALLBACK MCIWAVE_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
1719 {
1720  TRACE("(%08lX, %p, %08X, %08lX, %08lX)\n",
1721  dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1722 
1723  switch (wMsg) {
1724  case DRV_LOAD: return 1;
1725  case DRV_FREE: return 1;
1727  case DRV_CLOSE: return WAVE_drvClose(dwDevID);
1728  case DRV_ENABLE: return 1;
1729  case DRV_DISABLE: return 1;
1730  case DRV_QUERYCONFIGURE: return 1;
1731  case DRV_CONFIGURE: MessageBoxA(0, "MCI waveaudio Driver !", "Wine Driver", MB_OK); return 1;
1732  case DRV_INSTALL: return DRVCNF_RESTART;
1733  case DRV_REMOVE: return DRVCNF_RESTART;
1734  }
1735 
1736  if (dwDevID == 0xFFFFFFFF) return MCIERR_UNSUPPORTED_FUNCTION;
1737 
1738  switch (wMsg) {
1741  case MCI_CUE: return WAVE_mciCue (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
1742  case MCI_PLAY: return WAVE_mciPlay (dwDevID, dwParam1, dwParam2, NULL);
1743  case MCI_RECORD: return WAVE_mciRecord (dwDevID, dwParam1, dwParam2, NULL);
1744  case MCI_STOP: return WAVE_mciStop (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
1745  case MCI_SET: return WAVE_mciSet (dwDevID, dwParam1, (LPMCI_WAVE_SET_PARMS) dwParam2);
1746  case MCI_PAUSE: return WAVE_mciPause (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
1747  case MCI_RESUME: return WAVE_mciResume (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
1748  case MCI_STATUS: return WAVE_mciStatus (dwDevID, dwParam1, (LPMCI_STATUS_PARMS) dwParam2);
1750  case MCI_INFO: return WAVE_mciInfo (dwDevID, dwParam1, (LPMCI_INFO_PARMSW) dwParam2);
1751  case MCI_SEEK: return WAVE_mciSeek (dwDevID, dwParam1, (LPMCI_SEEK_PARMS) dwParam2);
1752  case MCI_SAVE: return WAVE_mciSave (dwDevID, dwParam1, (LPMCI_SAVE_PARMSW) dwParam2);
1753  /* commands that should be supported */
1754  case MCI_LOAD:
1755  case MCI_FREEZE:
1756  case MCI_PUT:
1757  case MCI_REALIZE:
1758  case MCI_UNFREEZE:
1759  case MCI_UPDATE:
1760  case MCI_WHERE:
1761  case MCI_STEP:
1762  case MCI_SPIN:
1763  case MCI_ESCAPE:
1764  case MCI_COPY:
1765  case MCI_CUT:
1766  case MCI_DELETE:
1767  case MCI_PASTE:
1768  FIXME("Unsupported command [%u]\n", wMsg);
1769  break;
1770  case MCI_WINDOW:
1771  TRACE("Unsupported command [%u]\n", wMsg);
1772  break;
1773  /* option which can be silenced */
1774  case MCI_CONFIGURE:
1775  return 0;
1776  case MCI_OPEN:
1777  case MCI_CLOSE:
1778  ERR("Shouldn't receive a MCI_OPEN or CLOSE message\n");
1779  break;
1780  default:
1781  FIXME("is probably wrong msg [%u]\n", wMsg);
1782  return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1783  }
1785 }
#define MCI_WAVE_GETDEVCAPS_INPUTS
Definition: mmsystem.h:839
Definition: mciwave.c:72
#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:701
#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:398
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:740
#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
#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:214
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:111
static DWORD WAVE_mciSave(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_SAVE_PARMSW lpParms)
Definition: mciwave.c:1420
DWORD dwDataOffset
Definition: mmsystem.h:1510
HANDLE evt
Definition: mciwave.c:74
HMMIO hFile
Definition: mciwave.c:43
#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:1167
#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:228
#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:407
async_cmd cmd
Definition: mciwave.c:73
#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:45
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:397
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:462
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:52
#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:54
#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:47
#define debugstr_w
Definition: kernel32.h:32
#define MCI_MODE_PLAY
Definition: mmsystem.h:696
#define FIXME(fmt,...)
Definition: debug.h:110
WORD wBitsPerSample
Definition: audioclient.idl:45
static LRESULT WAVE_drvClose(MCIDEVICEID dwDevID)
Definition: mciwave.c:181
DWORD(* async_cmd)(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt, HANDLE evt)
Definition: mciwave.c:70
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:724
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:582
BOOL fInput
Definition: mciwave.c:49
#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:51
#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:334
#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:347
#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:77
LPWSTR lpFileName
Definition: mciwave.c:46
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define WAVE_MAPPER
Definition: mmsystem.h:187
#define GetProcessHeap()
Definition: compat.h:395
LPWAVEFORMATEX lpWaveFormat
Definition: mciwave.c:48
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
static object_header_t ** handles
Definition: handle.c:46
#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:1207
#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:151
#define MCIERR_BAD_TIME_FORMAT
Definition: mmsystem.h:601
MCIDEVICEID wNotifyDeviceID
Definition: mciwave.c:44
#define MAX_PATH
Definition: compat.h:26
WORD wInput
Definition: mciwave.c:50
#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:409
#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:100
#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:1001
#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:332
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:196
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:985
static DWORD WAVE_mciReadFmt(WINE_MCIWAVE *wmw, const MMCKINFO *pckMainRIFF)
Definition: mciwave.c:279
UINT wDevID
Definition: mciwave.c:40
uint32_t DWORD_PTR
Definition: typedefs.h:63
_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:335
static void CALLBACK WAVE_mciRecordCallback(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance, LPARAM dwParam1, LPARAM dwParam2)
Definition: mciwave.c:942
#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:109
static DWORD WAVE_mciSeek(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
Definition: mciwave.c:1250
DWORD_PTR dwCallback
Definition: mmsystem.h:1566
MMCKINFO ckWaveData
Definition: mciwave.c:58
#define HWND_32(h16)
Definition: wownt32.h:29
static DWORD WAVE_mciStop(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
Definition: mciwave.c:619
MMCKINFO ckMainRIFF
Definition: mciwave.c:57
#define MCIERR_FILE_NOT_FOUND
Definition: mmsystem.h:585
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
#define InterlockedIncrement
Definition: armddk.h:53
#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:1472
#define MCI_OPEN_ELEMENT
Definition: mmsystem.h:735
static LRESULT WAVE_mciOpen(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMSW lpOpenParms)
Definition: mciwave.c:515
DWORD_PTR dwParam1
Definition: mciwave.c:76
static DWORD create_tmp_file(HMMIO *hFile, LPWSTR *pszTmpFileName)
Definition: mciwave.c:419
LRESULT CALLBACK MCIWAVE_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg, LPARAM dwParam1, LPARAM dwParam2)
Definition: mciwave.c:1717
#define min(a, b)
Definition: monoChain.cc:55
UINT WINAPI waveOutClose(HWAVEOUT hWaveOut)
Definition: winmm.c:2260
HANDLE hEvent
Definition: mciwave.c:55
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:41
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:75
UINT MCIDEVICEID
Definition: mmsystem.h:959
static DWORD WAVE_mciGetDevCaps(MCIDEVICEID wDevID, DWORD dwFlags, LPMCI_GETDEVCAPS_PARMS lpParms)
Definition: mciwave.c:1600
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:83
DWORD dwMciTimeFormat
Definition: mciwave.c:53
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:1671
#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:252
#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:42
#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:56
#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:394
#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:661
#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:1294