mciwave: Play/Record return MCIERR_OUTOFRANGE as required.

This commit is contained in:
Jörg Höhle 2009-10-21 17:44:58 +02:00 committed by Alexandre Julliard
parent 7c62fe4639
commit 23060afdcd
2 changed files with 77 additions and 44 deletions

View File

@ -751,8 +751,6 @@ static DWORD WAVE_mciPlay(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt,
return WAVE_mciResume(wDevID, dwFlags, (LPMCI_GENERIC_PARMS)lpParms); return WAVE_mciResume(wDevID, dwFlags, (LPMCI_GENERIC_PARMS)lpParms);
} }
wmw->fInput = FALSE;
/** This function will be called again by a thread when async is used. /** This function will be called again by a thread when async is used.
* We have to set MCI_MODE_PLAY before we do this so that the app can spin * We have to set MCI_MODE_PLAY before we do this so that the app can spin
* on MCI_STATUS, so we have to allow it here if we're not going to start this thread. * on MCI_STATUS, so we have to allow it here if we're not going to start this thread.
@ -761,13 +759,6 @@ static DWORD WAVE_mciPlay(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt,
return MCIERR_INTERNAL; return MCIERR_INTERNAL;
} }
wmw->dwStatus = MCI_MODE_PLAY;
if (!(dwFlags & MCI_WAIT)) {
return MCI_SendCommandAsync(wmw->openParms.wDeviceID, WAVE_mciPlay, dwFlags,
(DWORD_PTR)lpParms, sizeof(MCI_PLAY_PARMS));
}
if (wmw->lpWaveFormat->wFormatTag == WAVE_FORMAT_PCM) { if (wmw->lpWaveFormat->wFormatTag == WAVE_FORMAT_PCM) {
if (wmw->lpWaveFormat->nBlockAlign != if (wmw->lpWaveFormat->nBlockAlign !=
wmw->lpWaveFormat->nChannels * wmw->lpWaveFormat->wBitsPerSample/8) { wmw->lpWaveFormat->nChannels * wmw->lpWaveFormat->wBitsPerSample/8) {
@ -791,12 +782,30 @@ static DWORD WAVE_mciPlay(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt,
} }
} }
end = 0xFFFFFFFF; end = wmw->ckWaveData.cksize;
if (lpParms && (dwFlags & MCI_FROM)) {
wmw->dwPosition = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwFrom);
}
if (lpParms && (dwFlags & MCI_TO)) { if (lpParms && (dwFlags & MCI_TO)) {
end = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwTo); DWORD position = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwTo);
if (position > end) return MCIERR_OUTOFRANGE;
end = position;
}
if (lpParms && (dwFlags & MCI_FROM)) {
DWORD position = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwFrom);
if (position > end) return MCIERR_OUTOFRANGE;
/* Seek rounds down, so do we. */
position /= wmw->lpWaveFormat->nBlockAlign;
position *= wmw->lpWaveFormat->nBlockAlign;
wmw->dwPosition = position;
}
if (end < wmw->dwPosition) return MCIERR_OUTOFRANGE;
left = end - wmw->dwPosition;
if (0==left) return MMSYSERR_NOERROR; /* FIXME: NOTIFY */
wmw->fInput = FALSE; /* FIXME: waveInOpen may have been called. */
wmw->dwStatus = MCI_MODE_PLAY;
if (!(dwFlags & MCI_WAIT)) {
return MCI_SendCommandAsync(wmw->openParms.wDeviceID, WAVE_mciPlay, dwFlags,
(DWORD_PTR)lpParms, sizeof(MCI_PLAY_PARMS));
} }
TRACE("Playing from byte=%u to byte=%u\n", wmw->dwPosition, end); TRACE("Playing from byte=%u to byte=%u\n", wmw->dwPosition, end);
@ -806,17 +815,9 @@ static DWORD WAVE_mciPlay(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt,
if (oldcb) mciDriverNotify(oldcb, wDevID, MCI_NOTIFY_ABORTED); if (oldcb) mciDriverNotify(oldcb, wDevID, MCI_NOTIFY_ABORTED);
oldcb = NULL; oldcb = NULL;
if (end <= wmw->dwPosition)
return MMSYSERR_NOERROR;
#define WAVE_ALIGN_ON_BLOCK(wmw,v) \ #define WAVE_ALIGN_ON_BLOCK(wmw,v) \
((((v) + (wmw)->lpWaveFormat->nBlockAlign - 1) / (wmw)->lpWaveFormat->nBlockAlign) * (wmw)->lpWaveFormat->nBlockAlign) ((((v) + (wmw)->lpWaveFormat->nBlockAlign - 1) / (wmw)->lpWaveFormat->nBlockAlign) * (wmw)->lpWaveFormat->nBlockAlign)
wmw->dwPosition = WAVE_ALIGN_ON_BLOCK(wmw, wmw->dwPosition);
wmw->ckWaveData.cksize = WAVE_ALIGN_ON_BLOCK(wmw, wmw->ckWaveData.cksize);
/* go back to beginning of chunk plus the requested position */ /* go back to beginning of chunk plus the requested position */
/* FIXME: I'm not sure this is correct, notably because some data linked to /* FIXME: I'm not sure this is correct, notably because some data linked to
* the decompression state machine will not be correctly initialized. * the decompression state machine will not be correctly initialized.
@ -825,9 +826,6 @@ static DWORD WAVE_mciPlay(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt,
*/ */
mmioSeek(wmw->hFile, wmw->ckWaveData.dwDataOffset + wmw->dwPosition, SEEK_SET); /* >= 0 */ mmioSeek(wmw->hFile, wmw->ckWaveData.dwDataOffset + wmw->dwPosition, SEEK_SET); /* >= 0 */
/* By default the device will be opened for output, the MCI_CUE function is there to
* change from output to input and back
*/
/* FIXME: how to choose between several output channels ? here mapper is forced */ /* FIXME: how to choose between several output channels ? here mapper is forced */
dwRet = waveOutOpen((HWAVEOUT *)&wmw->hWave, WAVE_MAPPER, wmw->lpWaveFormat, dwRet = waveOutOpen((HWAVEOUT *)&wmw->hWave, WAVE_MAPPER, wmw->lpWaveFormat,
(DWORD_PTR)WAVE_mciPlayCallback, (DWORD_PTR)wmw, CALLBACK_FUNCTION); (DWORD_PTR)WAVE_mciPlayCallback, (DWORD_PTR)wmw, CALLBACK_FUNCTION);
@ -856,7 +854,6 @@ static DWORD WAVE_mciPlay(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt,
} }
whidx = 0; whidx = 0;
left = min(wmw->ckWaveData.cksize, end - wmw->dwPosition);
wmw->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); wmw->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
wmw->dwEventCount = 1L; /* for first buffer */ wmw->dwEventCount = 1L; /* for first buffer */
@ -999,11 +996,6 @@ static DWORD WAVE_mciRecord(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt
return WAVE_mciResume(wDevID, dwFlags, (LPMCI_GENERIC_PARMS)lpParms); return WAVE_mciResume(wDevID, dwFlags, (LPMCI_GENERIC_PARMS)lpParms);
} }
/* FIXME : since there is no way to determine in which mode the device is
* open (recording/playback) automatically switch from a mode to another
*/
wmw->fInput = TRUE;
/** This function will be called again by a thread when async is used. /** This function will be called again by a thread when async is used.
* We have to set MCI_MODE_RECORD before we do this so that the app can spin * We have to set MCI_MODE_RECORD before we do this so that the app can spin
* on MCI_STATUS, so we have to allow it here if we're not going to start this thread. * on MCI_STATUS, so we have to allow it here if we're not going to start this thread.
@ -1012,6 +1004,7 @@ static DWORD WAVE_mciRecord(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt
return MCIERR_INTERNAL; return MCIERR_INTERNAL;
} }
wmw->fInput = TRUE; /* FIXME: waveOutOpen may have been called. */
wmw->dwStatus = MCI_MODE_RECORD; wmw->dwStatus = MCI_MODE_RECORD;
if (!(dwFlags & MCI_WAIT)) { if (!(dwFlags & MCI_WAIT)) {
@ -1027,18 +1020,22 @@ static DWORD WAVE_mciRecord(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt
dwRet = create_tmp_file(&wmw->hFile, (WCHAR**)&wmw->openParms.lpstrElementName); dwRet = create_tmp_file(&wmw->hFile, (WCHAR**)&wmw->openParms.lpstrElementName);
if (dwRet != 0) return dwRet; if (dwRet != 0) return dwRet;
/* new RIFF file */ /* new RIFF file, lpWaveFormat now valid */
dwRet = WAVE_mciCreateRIFFSkeleton(wmw); dwRet = WAVE_mciCreateRIFFSkeleton(wmw);
if (dwRet != 0) return dwRet; if (dwRet != 0) return dwRet;
end = 0xFFFFFFFF;
if (lpParms && (dwFlags & MCI_FROM)) {
wmw->dwPosition = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwFrom);
}
if (lpParms && (dwFlags & MCI_TO)) { if (lpParms && (dwFlags & MCI_TO)) {
end = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwTo); end = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwTo);
} else end = 0xFFFFFFFF;
if (lpParms && (dwFlags & MCI_FROM)) {
DWORD position = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwFrom);
if (wmw->ckWaveData.cksize < position) return MCIERR_OUTOFRANGE;
/* Seek rounds down, so do we. */
position /= wmw->lpWaveFormat->nBlockAlign;
position *= wmw->lpWaveFormat->nBlockAlign;
wmw->dwPosition = position;
} }
if (end==wmw->dwPosition) return MMSYSERR_NOERROR; /* FIXME: NOTIFY */
TRACE("Recording from byte=%u to byte=%u\n", wmw->dwPosition, end); TRACE("Recording from byte=%u to byte=%u\n", wmw->dwPosition, end);
@ -1047,15 +1044,9 @@ static DWORD WAVE_mciRecord(MCIDEVICEID wDevID, DWORD_PTR dwFlags, DWORD_PTR pmt
if (oldcb) mciDriverNotify(oldcb, wDevID, MCI_NOTIFY_ABORTED); if (oldcb) mciDriverNotify(oldcb, wDevID, MCI_NOTIFY_ABORTED);
oldcb = NULL; oldcb = NULL;
if (end <= wmw->dwPosition)
{
return MMSYSERR_NOERROR;
}
#define WAVE_ALIGN_ON_BLOCK(wmw,v) \ #define WAVE_ALIGN_ON_BLOCK(wmw,v) \
((((v) + (wmw)->lpWaveFormat->nBlockAlign - 1) / (wmw)->lpWaveFormat->nBlockAlign) * (wmw)->lpWaveFormat->nBlockAlign) ((((v) + (wmw)->lpWaveFormat->nBlockAlign - 1) / (wmw)->lpWaveFormat->nBlockAlign) * (wmw)->lpWaveFormat->nBlockAlign)
wmw->dwPosition = WAVE_ALIGN_ON_BLOCK(wmw, wmw->dwPosition);
wmw->ckWaveData.cksize = WAVE_ALIGN_ON_BLOCK(wmw, wmw->ckWaveData.cksize); wmw->ckWaveData.cksize = WAVE_ALIGN_ON_BLOCK(wmw, wmw->ckWaveData.cksize);
/* Go back to the beginning of the chunk plus the requested position */ /* Go back to the beginning of the chunk plus the requested position */

View File

@ -332,7 +332,22 @@ static void test_playWAVE(HWND hwnd)
err = mciSendString("cue output", NULL, 0, NULL); err = mciSendString("cue output", NULL, 0, NULL);
todo_wine ok(err==MCIERR_UNRECOGNIZED_COMMAND,"mci incorrect cue output returned: %s\n", dbg_mcierr(err)); todo_wine ok(err==MCIERR_UNRECOGNIZED_COMMAND,"mci incorrect cue output returned: %s\n", dbg_mcierr(err));
/* A second play would cause Wine to hang */ err = mciSendString("play mysound from 0 to 0 notify", NULL, 0, hwnd);
ok(!err,"mci play from 0 to 0 returned error: %d\n", err);
todo_wine test_notification1(hwnd,"play from 0 to 0",MCI_NOTIFY_SUCCESSFUL);
err = mciSendString("status mysound mode", buf, sizeof(buf), hwnd);
ok(!err,"mci status mode returned error: %d\n", err);
ok(!strcmp(buf,"stopped"), "mci status mode: %s\n", buf);
err = mciSendString("play mysound from 250 to 0", NULL, 0, NULL);
ok(err==MCIERR_OUTOFRANGE,"mci play from 250 to 0 returned error: %d\n", err);
err = mciSendString("play mysound from 250 to 0 notify", NULL, 0, hwnd);
ok(err==MCIERR_OUTOFRANGE,"mci play from 250 to 0 notify returned error: %d\n", err);
/* No notification (checked below) sent if error */
/* A second play caused Wine to hang */
err = mciSendString("play mysound from 500 to 1500 wait", NULL, 0, NULL); err = mciSendString("play mysound from 500 to 1500 wait", NULL, 0, NULL);
ok(!err,"mci play from 500 to 1500 returned error: %d\n", err); ok(!err,"mci play from 500 to 1500 returned error: %d\n", err);
@ -341,6 +356,29 @@ static void test_playWAVE(HWND hwnd)
ok(!err,"mci status position returned error: %d\n", err); ok(!err,"mci status position returned error: %d\n", err);
if(!err) ok(!strcmp(buf,"1500"), "mci status position: %s\n", buf); if(!err) ok(!strcmp(buf,"1500"), "mci status position: %s\n", buf);
/* mci will not play position < current */
err = mciSendString("play mysound to 1000", NULL, 0, NULL);
ok(err==MCIERR_OUTOFRANGE,"mci play to 1000 returned error: %d\n", err);
/* mci will not play to > end */
err = mciSendString("play mysound to 3000 notify", NULL, 0, hwnd);
ok(err==MCIERR_OUTOFRANGE,"mci play to 3000 notify returned error: %d\n", err);
/* Again, no notification upon error */
err = mciSendString("play mysound to 2000", NULL, 0, NULL);
ok(!err,"mci play to 2000 returned error: %d\n", err);
/* Rejected while playing */
err = mciSendString("cue mysound output", NULL, 0, NULL);
ok(err==MCIERR_NONAPPLICABLE_FUNCTION,"mci cue output while playing returned error: %d\n", err);
err = mciSendString("play mysound to 3000", NULL, 0, NULL);
ok(err==MCIERR_OUTOFRANGE,"mci play to 3000 returned error: %d\n", err);
err = mciSendString("stop mysound wait", NULL, 0, NULL);
ok(!err,"mci stop wait returned error: %d\n", err);
test_notification(hwnd,"play outofrange notify #2",0);
err = mciSendString("seek mysound to 250 wait notify", NULL, 0, hwnd); err = mciSendString("seek mysound to 250 wait notify", NULL, 0, hwnd);
ok(!err,"mci seek to 250 wait notify returned error: %d\n", err); ok(!err,"mci seek to 250 wait notify returned error: %d\n", err);
test_notification(hwnd,"seek wait notify",MCI_NOTIFY_SUCCESSFUL); test_notification(hwnd,"seek wait notify",MCI_NOTIFY_SUCCESSFUL);
@ -357,6 +395,10 @@ static void test_playWAVE(HWND hwnd)
ok(!err,"mci status mode returned error: %d\n", err); ok(!err,"mci status mode returned error: %d\n", err);
ok(!strcmp(buf,"stopped"), "mci status mode: %s\n", buf); ok(!strcmp(buf,"stopped"), "mci status mode: %s\n", buf);
err = mciSendString("play mysound to 250 wait notify", NULL, 0, hwnd);
ok(!err,"mci play to 250 returned error: %d\n", err);
todo_wine test_notification1(hwnd,"play to 250 wait notify",MCI_NOTIFY_SUCCESSFUL);
err = mciSendString("close mysound", NULL, 0, NULL); err = mciSendString("close mysound", NULL, 0, NULL);
ok(!err,"mci close returned error: %d\n", err); ok(!err,"mci close returned error: %d\n", err);
test_notification(hwnd,"after close",0); test_notification(hwnd,"after close",0);