Commit eed1b520 authored by Francois Gouget's avatar Francois Gouget Committed by Alexandre Julliard

Added bytes_to_mmtime() to convert the stream position from bytes to

the requested MMTIME format. This function should be identical in all drivers. Remove the corresponding code from wodGetPosition() and widGetPosition() and use bytes_to_mmtime() instead. bytes_to_mmtime() uses no floating-point arithmetic to compute TIME_SMPTE and no longer uses round(). It should have no integer overflows either.
parent 1dc308ec
...@@ -258,6 +258,55 @@ static const char *wodPlayerCmdString[] = { ...@@ -258,6 +258,55 @@ static const char *wodPlayerCmdString[] = {
}; };
#endif #endif
static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
PCMWAVEFORMAT* format)
{
TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
format->wf.nChannels, format->wf.nAvgBytesPerSec);
TRACE("Position in bytes=%lu\n", position);
switch (lpTime->wType) {
case TIME_SAMPLES:
lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_MS:
lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
case TIME_SMPTE:
position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
lpTime->u.smpte.fps = 30;
lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
if (position != 0)
{
/* Round up */
lpTime->u.smpte.frame++;
}
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
lpTime->wType = TIME_BYTES;
/* fall through */
case TIME_BYTES:
lpTime->u.cb = position;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
}
return MMSYSERR_NOERROR;
}
/*======================================================================* /*======================================================================*
* Low level WAVE implementation * * Low level WAVE implementation *
*======================================================================*/ *======================================================================*/
...@@ -1835,8 +1884,6 @@ static DWORD wodReset(WORD wDevID) ...@@ -1835,8 +1884,6 @@ static DWORD wodReset(WORD wDevID)
*/ */
static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{ {
double time;
DWORD val;
WINE_WAVEOUT* wwo; WINE_WAVEOUT* wwo;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize); TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
...@@ -1850,46 +1897,8 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) ...@@ -1850,46 +1897,8 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
wwo = &WOutDev[wDevID]; wwo = &WOutDev[wDevID];
ALSA_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE); ALSA_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);
val = wwo->dwPlayedTotal;
TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
lpTime->wType, wwo->format.wBitsPerSample,
wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
wwo->format.wf.nAvgBytesPerSec);
TRACE("dwPlayedTotal=%lu\n", val);
switch (lpTime->wType) { return bytes_to_mmtime(lpTime, wwo->dwPlayedTotal, &wwo->format);
case TIME_BYTES:
lpTime->u.cb = val;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
case TIME_SAMPLES:
lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_SMPTE:
time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
lpTime->u.smpte.hour = time / (60 * 60);
time -= lpTime->u.smpte.hour * (60 * 60);
lpTime->u.smpte.min = time / 60;
time -= lpTime->u.smpte.min * 60;
lpTime->u.smpte.sec = time;
time -= lpTime->u.smpte.sec;
lpTime->u.smpte.frame = round(time * 30);
lpTime->u.smpte.fps = 30;
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
lpTime->wType = TIME_MS;
case TIME_MS:
lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
}
return MMSYSERR_NOERROR;
} }
/************************************************************************** /**************************************************************************
...@@ -3338,7 +3347,6 @@ static DWORD widReset(WORD wDevID) ...@@ -3338,7 +3347,6 @@ static DWORD widReset(WORD wDevID)
*/ */
static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{ {
double time;
WINE_WAVEIN* wwi; WINE_WAVEIN* wwi;
FIXME("(%u, %p, %lu);\n", wDevID, lpTime, uSize); FIXME("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
...@@ -3352,47 +3360,7 @@ static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) ...@@ -3352,47 +3360,7 @@ static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
wwi = &WInDev[wDevID]; wwi = &WInDev[wDevID];
ALSA_AddRingMessage(&wwi->msgRing, WINE_WM_UPDATE, 0, TRUE); ALSA_AddRingMessage(&wwi->msgRing, WINE_WM_UPDATE, 0, TRUE);
TRACE("wType=%04X !\n", lpTime->wType); return bytes_to_mmtime(lpTime, wwi->dwTotalRecorded, &wwi->format);
TRACE("wBitsPerSample=%u\n", wwi->format.wBitsPerSample);
TRACE("nSamplesPerSec=%lu\n", wwi->format.wf.nSamplesPerSec);
TRACE("nChannels=%u\n", wwi->format.wf.nChannels);
TRACE("nAvgBytesPerSec=%lu\n", wwi->format.wf.nAvgBytesPerSec);
FIXME("dwTotalRecorded=%lu\n",wwi->dwTotalRecorded);
switch (lpTime->wType) {
case TIME_BYTES:
lpTime->u.cb = wwi->dwTotalRecorded;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
case TIME_SAMPLES:
lpTime->u.sample = wwi->dwTotalRecorded * 8 /
wwi->format.wBitsPerSample / wwi->format.wf.nChannels;
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_SMPTE:
time = (double)wwi->dwTotalRecorded /
(double)wwi->format.wf.nAvgBytesPerSec;
lpTime->u.smpte.hour = time / (60 * 60);
time -= lpTime->u.smpte.hour * (60 * 60);
lpTime->u.smpte.min = time / 60;
time -= lpTime->u.smpte.min * 60;
lpTime->u.smpte.sec = time;
time -= lpTime->u.smpte.sec;
lpTime->u.smpte.frame = ceil(time * 30);
lpTime->u.smpte.fps = 30;
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("format not supported (%u) ! use TIME_MS !\n", lpTime->wType);
lpTime->wType = TIME_MS;
case TIME_MS:
lpTime->u.ms = wwi->dwTotalRecorded * 1000.0 /
wwi->format.wf.nAvgBytesPerSec;
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
}
return MMSYSERR_NOERROR;
} }
/************************************************************************** /**************************************************************************
......
...@@ -222,6 +222,55 @@ static const char *wodPlayerCmdString[] = { ...@@ -222,6 +222,55 @@ static const char *wodPlayerCmdString[] = {
"WINE_WM_STOPPING", "WINE_WM_STOPPING",
}; };
static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
PCMWAVEFORMAT* format)
{
TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
format->wf.nChannels, format->wf.nAvgBytesPerSec);
TRACE("Position in bytes=%lu\n", position);
switch (lpTime->wType) {
case TIME_SAMPLES:
lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_MS:
lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
case TIME_SMPTE:
position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
lpTime->u.smpte.fps = 30;
lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
if (position != 0)
{
/* Round up */
lpTime->u.smpte.frame++;
}
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
lpTime->wType = TIME_BYTES;
/* fall through */
case TIME_BYTES:
lpTime->u.cb = position;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
}
return MMSYSERR_NOERROR;
}
/*======================================================================* /*======================================================================*
* Low level WAVE implementation * * Low level WAVE implementation *
*======================================================================*/ *======================================================================*/
...@@ -1386,8 +1435,6 @@ static DWORD wodReset(WORD wDevID) ...@@ -1386,8 +1435,6 @@ static DWORD wodReset(WORD wDevID)
*/ */
static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{ {
double time;
DWORD val;
WINE_WAVEOUT* wwo; WINE_WAVEOUT* wwo;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize); TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
...@@ -1403,46 +1450,8 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) ...@@ -1403,46 +1450,8 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
wwo = &WOutDev[wDevID]; wwo = &WOutDev[wDevID];
ARTS_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE); ARTS_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);
val = wwo->dwPlayedTotal;
TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n", return bytes_to_mmtime(lpTime, wwo->dwPlayedTotal, &wwo->format);
lpTime->wType, wwo->format.wBitsPerSample,
wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
wwo->format.wf.nAvgBytesPerSec);
TRACE("dwPlayedTotal=%lu\n", val);
switch (lpTime->wType) {
case TIME_BYTES:
lpTime->u.cb = val;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
case TIME_SAMPLES:
lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_SMPTE:
time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
lpTime->u.smpte.hour = time / (60 * 60);
time -= lpTime->u.smpte.hour * (60 * 60);
lpTime->u.smpte.min = time / 60;
time -= lpTime->u.smpte.min * 60;
lpTime->u.smpte.sec = time;
time -= lpTime->u.smpte.sec;
lpTime->u.smpte.frame = round(time * 30);
lpTime->u.smpte.fps = 30;
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
lpTime->wType = TIME_MS;
case TIME_MS:
lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
}
return MMSYSERR_NOERROR;
} }
/************************************************************************** /**************************************************************************
......
...@@ -185,6 +185,55 @@ static DWORD widDsDesc(UINT wDevID, PDSDRIVERDESC desc); ...@@ -185,6 +185,55 @@ static DWORD widDsDesc(UINT wDevID, PDSDRIVERDESC desc);
static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid); static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid);
static DWORD widDsGuid(UINT wDevID, LPGUID pGuid); static DWORD widDsGuid(UINT wDevID, LPGUID pGuid);
static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
PCMWAVEFORMAT* format)
{
TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
format->wf.nChannels, format->wf.nAvgBytesPerSec);
TRACE("Position in bytes=%lu\n", position);
switch (lpTime->wType) {
case TIME_SAMPLES:
lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_MS:
lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
case TIME_SMPTE:
position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
lpTime->u.smpte.fps = 30;
lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
if (position != 0)
{
/* Round up */
lpTime->u.smpte.frame++;
}
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
lpTime->wType = TIME_BYTES;
/* fall through */
case TIME_BYTES:
lpTime->u.cb = position;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
}
return MMSYSERR_NOERROR;
}
/*======================================================================* /*======================================================================*
* Low level WAVE implementation * * Low level WAVE implementation *
*======================================================================*/ *======================================================================*/
...@@ -1082,8 +1131,6 @@ static DWORD wodReset(WORD wDevID) ...@@ -1082,8 +1131,6 @@ static DWORD wodReset(WORD wDevID)
*/ */
static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{ {
double time;
DWORD val;
WINE_WAVEOUT* wwo; WINE_WAVEOUT* wwo;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize); TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
...@@ -1096,46 +1143,8 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) ...@@ -1096,46 +1143,8 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
if (lpTime == NULL) return MMSYSERR_INVALPARAM; if (lpTime == NULL) return MMSYSERR_INVALPARAM;
wwo = &WOutDev[wDevID]; wwo = &WOutDev[wDevID];
val = wwo->dwPlayedTotal;
TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
lpTime->wType, wwo->format.wBitsPerSample,
wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
wwo->format.wf.nAvgBytesPerSec);
TRACE("dwTotalPlayed=%lu\n", val);
switch (lpTime->wType) { return bytes_to_mmtime(lpTime, wwo->dwPlayedTotal, &wwo->format);
case TIME_BYTES:
lpTime->u.cb = val;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
case TIME_SAMPLES:
lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample;
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_SMPTE:
time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
lpTime->u.smpte.hour = time / (60 * 60);
time -= lpTime->u.smpte.hour * (60 * 60);
lpTime->u.smpte.min = time / 60;
time -= lpTime->u.smpte.min * 60;
lpTime->u.smpte.sec = time;
time -= lpTime->u.smpte.sec;
lpTime->u.smpte.frame = round(time * 30);
lpTime->u.smpte.fps = 30;
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
lpTime->wType = TIME_MS;
case TIME_MS:
lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
}
return MMSYSERR_NOERROR;
} }
/************************************************************************** /**************************************************************************
...@@ -2205,7 +2214,6 @@ static DWORD widReset(WORD wDevID) ...@@ -2205,7 +2214,6 @@ static DWORD widReset(WORD wDevID)
*/ */
static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{ {
double time;
WINE_WAVEIN* wwi; WINE_WAVEIN* wwi;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize); TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
...@@ -2218,46 +2226,7 @@ static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) ...@@ -2218,46 +2226,7 @@ static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
wwi = &WInDev[wDevID]; wwi = &WInDev[wDevID];
TRACE("wType=%04X !\n", lpTime->wType); return bytes_to_mmtime(lpTime, wwi->dwTotalRecorded, &wwi->format);
TRACE("wBitsPerSample=%u\n", wwi->format.wBitsPerSample);
TRACE("nSamplesPerSec=%lu\n", wwi->format.wf.nSamplesPerSec);
TRACE("nChannels=%u\n", wwi->format.wf.nChannels);
TRACE("nAvgBytesPerSec=%lu\n", wwi->format.wf.nAvgBytesPerSec);
switch (lpTime->wType) {
case TIME_BYTES:
lpTime->u.cb = wwi->dwTotalRecorded;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
case TIME_SAMPLES:
lpTime->u.sample = wwi->dwTotalRecorded * 8 /
wwi->format.wBitsPerSample;
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_SMPTE:
time = (double)wwi->dwTotalRecorded /
(double)wwi->format.wf.nAvgBytesPerSec;
lpTime->u.smpte.hour = time / (60 * 60);
time -= lpTime->u.smpte.hour * (60 * 60);
lpTime->u.smpte.min = time / 60;
time -= lpTime->u.smpte.min * 60;
lpTime->u.smpte.sec = time;
time -= lpTime->u.smpte.sec;
lpTime->u.smpte.frame = celi(time * 30);
lpTime->u.smpte.fps = 30;
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
case TIME_MS:
lpTime->u.ms = wwi->dwTotalRecorded * 1000.0 /
wwi->format.wf.nAvgBytesPerSec;
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
default:
FIXME("format not supported (%u) ! use TIME_MS !\n", lpTime->wType);
lpTime->wType = TIME_MS;
}
return MMSYSERR_NOERROR;
} }
/************************************************************************** /**************************************************************************
......
...@@ -215,6 +215,55 @@ static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client); ...@@ -215,6 +215,55 @@ static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi, BOOL close_client);
static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi); static void JACK_CloseWaveInDevice(WINE_WAVEIN* wwi);
#endif #endif
static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
PCMWAVEFORMAT* format)
{
TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
format->wf.nChannels, format->wf.nAvgBytesPerSec);
TRACE("Position in bytes=%lu\n", position);
switch (lpTime->wType) {
case TIME_SAMPLES:
lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_MS:
lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
case TIME_SMPTE:
position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
lpTime->u.smpte.fps = 30;
lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
if (position != 0)
{
/* Round up */
lpTime->u.smpte.frame++;
}
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
lpTime->wType = TIME_BYTES;
/* fall through */
case TIME_BYTES:
lpTime->u.cb = position;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
}
return MMSYSERR_NOERROR;
}
/*======================================================================* /*======================================================================*
* Low level WAVE implementation * * Low level WAVE implementation *
...@@ -1542,19 +1591,18 @@ static DWORD wodReset(WORD wDevID) ...@@ -1542,19 +1591,18 @@ static DWORD wodReset(WORD wDevID)
*/ */
static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{ {
double time;
DWORD val; DWORD val;
WINE_WAVEOUT* wwo; WINE_WAVEOUT* wwo;
DWORD elapsedMS; DWORD elapsedMS;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize); TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client) if (wDevID >= MAX_WAVEOUTDRV || !WOutDev[wDevID].client)
{ {
WARN("bad device ID !\n"); WARN("bad device ID !\n");
return MMSYSERR_BADDEVICEID; return MMSYSERR_BADDEVICEID;
} }
/* if null pointer to time structure return error */ /* if null pointer to time structure return error */
if (lpTime == NULL) return MMSYSERR_INVALPARAM; if (lpTime == NULL) return MMSYSERR_INVALPARAM;
...@@ -1568,44 +1616,7 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) ...@@ -1568,44 +1616,7 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
/* account for the bytes played since the last JACK_Callback() */ /* account for the bytes played since the last JACK_Callback() */
val+=((elapsedMS * wwo->format.wf.nAvgBytesPerSec) / 1000); val+=((elapsedMS * wwo->format.wf.nAvgBytesPerSec) / 1000);
TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n", return bytes_to_mmtime(lpTime, val, &wwo->format);
lpTime->wType, wwo->format.wBitsPerSample,
wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
wwo->format.wf.nAvgBytesPerSec);
TRACE("dwPlayedTotal=%lu\n", val);
switch (lpTime->wType) {
case TIME_BYTES:
lpTime->u.cb = val;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
case TIME_SAMPLES:
lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_SMPTE:
time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
lpTime->u.smpte.hour = time / (60 * 60);
time -= lpTime->u.smpte.hour * (60 * 60);
lpTime->u.smpte.min = time / 60;
time -= lpTime->u.smpte.min * 60;
lpTime->u.smpte.sec = time;
time -= lpTime->u.smpte.sec;
lpTime->u.smpte.frame = round(time * 30);
lpTime->u.smpte.fps = 30;
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
lpTime->wType = TIME_MS;
case TIME_MS:
lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
}
return MMSYSERR_NOERROR;
} }
/************************************************************************** /**************************************************************************
......
...@@ -279,6 +279,55 @@ static char* nas_state(unsigned int state) ...@@ -279,6 +279,55 @@ static char* nas_state(unsigned int state)
return nas_states[state]; return nas_states[state];
} }
static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
PCMWAVEFORMAT* format)
{
TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
format->wf.nChannels, format->wf.nAvgBytesPerSec);
TRACE("Position in bytes=%lu\n", position);
switch (lpTime->wType) {
case TIME_SAMPLES:
lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_MS:
lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
case TIME_SMPTE:
position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
lpTime->u.smpte.fps = 30;
lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
if (position != 0)
{
/* Round up */
lpTime->u.smpte.frame++;
}
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
lpTime->wType = TIME_BYTES;
/* fall through */
case TIME_BYTES:
lpTime->u.cb = position;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
}
return MMSYSERR_NOERROR;
}
/*======================================================================* /*======================================================================*
* Low level WAVE implementation * * Low level WAVE implementation *
*======================================================================*/ *======================================================================*/
...@@ -1122,8 +1171,6 @@ static DWORD wodReset(WORD wDevID) ...@@ -1122,8 +1171,6 @@ static DWORD wodReset(WORD wDevID)
*/ */
static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{ {
double time;
DWORD val;
WINE_WAVEOUT* wwo; WINE_WAVEOUT* wwo;
TRACE("%u, %p, %lu);\n", wDevID, lpTime, uSize); TRACE("%u, %p, %lu);\n", wDevID, lpTime, uSize);
...@@ -1140,46 +1187,8 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) ...@@ -1140,46 +1187,8 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
#if 0 #if 0
NAS_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE); NAS_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);
#endif #endif
val = wwo->WrittenTotal;
TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n", return bytes_to_mmtime(lpTime, wwo->WrittenTotal, &wwo->format);
lpTime->wType, wwo->format.wBitsPerSample,
wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
wwo->format.wf.nAvgBytesPerSec);
TRACE("PlayedTotal=%lu\n", val);
switch (lpTime->wType) {
case TIME_BYTES:
lpTime->u.cb = val;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
case TIME_SAMPLES:
lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample / wwo->format.wf.nChannels;
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_SMPTE:
time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
lpTime->u.smpte.hour = time / (60 * 60);
time -= lpTime->u.smpte.hour * (60 * 60);
lpTime->u.smpte.min = time / 60;
time -= lpTime->u.smpte.min * 60;
lpTime->u.smpte.sec = time;
time -= lpTime->u.smpte.sec;
lpTime->u.smpte.frame = round(time * 30);
lpTime->u.smpte.fps = 30;
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
lpTime->wType = TIME_MS;
case TIME_MS:
lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
}
return MMSYSERR_NOERROR;
} }
/************************************************************************** /**************************************************************************
......
...@@ -323,6 +323,55 @@ static DWORD wdDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2) ...@@ -323,6 +323,55 @@ static DWORD wdDevInterface(UINT wDevID, PWCHAR dwParam1, DWORD dwParam2)
return MMSYSERR_INVALPARAM; return MMSYSERR_INVALPARAM;
} }
static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
PCMWAVEFORMAT* format)
{
TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
lpTime->wType, format->wBitsPerSample, format->wf.nSamplesPerSec,
format->wf.nChannels, format->wf.nAvgBytesPerSec);
TRACE("Position in bytes=%lu\n", position);
switch (lpTime->wType) {
case TIME_SAMPLES:
lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_MS:
lpTime->u.ms = 1000.0 * position / (format->wBitsPerSample / 8 * format->wf.nChannels * format->wf.nSamplesPerSec);
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
case TIME_SMPTE:
position = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
lpTime->u.smpte.sec = position / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.sec * format->wf.nSamplesPerSec;
lpTime->u.smpte.min = lpTime->u.smpte.sec / 60;
lpTime->u.smpte.sec -= 60 * lpTime->u.smpte.min;
lpTime->u.smpte.hour = lpTime->u.smpte.min / 60;
lpTime->u.smpte.min -= 60 * lpTime->u.smpte.hour;
lpTime->u.smpte.fps = 30;
lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->wf.nSamplesPerSec;
position -= lpTime->u.smpte.frame * format->wf.nSamplesPerSec / lpTime->u.smpte.fps;
if (position != 0)
{
/* Round up */
lpTime->u.smpte.frame++;
}
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("Format %d not supported ! use TIME_BYTES !\n", lpTime->wType);
lpTime->wType = TIME_BYTES;
/* fall through */
case TIME_BYTES:
lpTime->u.cb = position;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
}
return MMSYSERR_NOERROR;
}
/*======================================================================* /*======================================================================*
* Low level WAVE implementation * * Low level WAVE implementation *
*======================================================================*/ *======================================================================*/
...@@ -2077,8 +2126,6 @@ static DWORD wodReset(WORD wDevID) ...@@ -2077,8 +2126,6 @@ static DWORD wodReset(WORD wDevID)
*/ */
static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{ {
double time;
DWORD val;
WINE_WAVEOUT* wwo; WINE_WAVEOUT* wwo;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize); TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
...@@ -2098,46 +2145,8 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) ...@@ -2098,46 +2145,8 @@ static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
if (wwo->ossdev->out_caps.dwSupport & WAVECAPS_SAMPLEACCURATE) if (wwo->ossdev->out_caps.dwSupport & WAVECAPS_SAMPLEACCURATE)
OSS_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE); OSS_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);
#endif #endif
val = wwo->dwPlayedTotal;
TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",
lpTime->wType, wwo->format.wBitsPerSample,
wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
wwo->format.wf.nAvgBytesPerSec);
TRACE("dwPlayedTotal=%lu\n", val);
switch (lpTime->wType) { return bytes_to_mmtime(lpTime, wwo->dwPlayedTotal, &wwo->format);
case TIME_BYTES:
lpTime->u.cb = val;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
case TIME_SAMPLES:
lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_SMPTE:
time = (double)val / (double)wwo->format.wf.nAvgBytesPerSec;
lpTime->u.smpte.hour = time / (60 * 60);
time -= lpTime->u.smpte.hour * (60 * 60);
lpTime->u.smpte.min = time / 60;
time -= lpTime->u.smpte.min * 60;
lpTime->u.smpte.sec = time;
time -= lpTime->u.smpte.sec;
lpTime->u.smpte.frame = round(time * 30);
lpTime->u.smpte.fps = 30;
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);
lpTime->wType = TIME_MS;
case TIME_MS:
lpTime->u.ms = val * 1000.0 / wwo->format.wf.nAvgBytesPerSec;
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
}
return MMSYSERR_NOERROR;
} }
/************************************************************************** /**************************************************************************
...@@ -3867,7 +3876,6 @@ static DWORD widReset(WORD wDevID) ...@@ -3867,7 +3876,6 @@ static DWORD widReset(WORD wDevID)
*/ */
static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
{ {
double time;
WINE_WAVEIN* wwi; WINE_WAVEIN* wwi;
TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize); TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
...@@ -3885,50 +3893,10 @@ static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) ...@@ -3885,50 +3893,10 @@ static DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
wwi = &WInDev[wDevID]; wwi = &WInDev[wDevID];
#ifdef EXACT_WIDPOSITION #ifdef EXACT_WIDPOSITION
if (wwi->ossdev->in_caps_support & WAVECAPS_SAMPLEACCURATE) if (wwi->ossdev->in_caps_support & WAVECAPS_SAMPLEACCURATE)
OSS_AddRingMessage(&(wwi->msgRing), WINE_WM_UPDATE, 0, TRUE); OSS_AddRingMessage(&(wwi->msgRing), WINE_WM_UPDATE, 0, TRUE);
#endif #endif
TRACE("wType=%04X !\n", lpTime->wType); return bytes_to_mmtime(lpTime, wwi->dwTotalRecorded, &wwi->format);
TRACE("wBitsPerSample=%u\n", wwi->format.wBitsPerSample);
TRACE("nSamplesPerSec=%lu\n", wwi->format.wf.nSamplesPerSec);
TRACE("nChannels=%u\n", wwi->format.wf.nChannels);
TRACE("nAvgBytesPerSec=%lu\n", wwi->format.wf.nAvgBytesPerSec);
TRACE("dwTotalRecorded=%lu\n",wwi->dwTotalRecorded);
switch (lpTime->wType) {
case TIME_BYTES:
lpTime->u.cb = wwi->dwTotalRecorded;
TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);
break;
case TIME_SAMPLES:
lpTime->u.sample = wwi->dwTotalRecorded * 8 /
wwi->format.wBitsPerSample / wwi->format.wf.nChannels;
TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);
break;
case TIME_SMPTE:
time = (double)wwi->dwTotalRecorded /
(double)wwi->format.wf.nAvgBytesPerSec;
lpTime->u.smpte.hour = time / (60 * 60);
time -= lpTime->u.smpte.hour * (60 * 60);
lpTime->u.smpte.min = time / 60;
time -= lpTime->u.smpte.min * 60;
lpTime->u.smpte.sec = time;
time -= lpTime->u.smpte.sec;
lpTime->u.smpte.frame = ceil(time * 30);
lpTime->u.smpte.fps = 30;
TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",
lpTime->u.smpte.hour, lpTime->u.smpte.min,
lpTime->u.smpte.sec, lpTime->u.smpte.frame);
break;
default:
FIXME("format not supported (%u) ! use TIME_MS !\n", lpTime->wType);
lpTime->wType = TIME_MS;
case TIME_MS:
lpTime->u.ms = wwi->dwTotalRecorded * 1000.0 /
wwi->format.wf.nAvgBytesPerSec;
TRACE("TIME_MS=%lu\n", lpTime->u.ms);
break;
}
return MMSYSERR_NOERROR;
} }
/************************************************************************** /**************************************************************************
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment