mciwave: Play/Record return MCIERR_OUTOFRANGE as required.
This commit is contained in:
parent
7c62fe4639
commit
23060afdcd
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue