Sync to Wine-20050310: Jeremy White jwhite@codeweavers.com - Aggressively round up to the proper alignment when reporting position on streams where we are converting up. - When we are converting from one sample rate to another, we do have to adjust when calculating TIME_SAMPLES. Alex Villacis Lasso a_villacis@palosanto.com - Change SUBLANG_DEFAULT to SUBLANG_NEUTRAL for LANG_SPANISH in all resources, so that Spanish locales other than Spain also use Spanish resources. Robert Reif reif@earthlink.net - Added parameter checking to timeGetDevCaps. - Added timer tests. Christian Costa titan.costa@wanadoo.fr - Added some more cases to MCI_MapMsgAtoW. - Fixed offsets calculations. Modified: trunk/reactos/lib/winmm/mci.c Modified: trunk/reactos/lib/winmm/time.c Modified: trunk/reactos/lib/winmm/wavemap/wavemap.c Modified: trunk/reactos/lib/winmm/winmm_Es.rc _____
Modified: trunk/reactos/lib/winmm/mci.c --- trunk/reactos/lib/winmm/mci.c 2005-03-15 21:39:07 UTC (rev 14105) +++ trunk/reactos/lib/winmm/mci.c 2005-03-15 21:44:42 UTC (rev 14106) @@ -278,6 +278,11 @@
case MCI_UPDATE: case MCI_RESUME: case MCI_DELETE: + case MCI_MONITOR: + case MCI_SETAUDIO: + case MCI_SIGNAL: + case MCI_SETVIDEO: + case MCI_LIST: return 0;
case MCI_OPEN: @@ -975,8 +980,8 @@ */ static DWORD MCI_GetReturnType(LPCWSTR lpCmd) { - lpCmd += strlenW(lpCmd) + 1 + sizeof(DWORD) + sizeof(WORD); - if (*lpCmd == '\0' && *(const WORD*)(lpCmd + 1 + sizeof(DWORD)) == MCI_RETURN) { + lpCmd = (LPCWSTR)((BYTE*)(lpCmd + strlenW(lpCmd) + 1) + sizeof(DWORD) + sizeof(WORD)); + if (*lpCmd == '\0' && *(const WORD*)((BYTE*)(lpCmd + 1) + sizeof(DWORD)) == MCI_RETURN) { return *(const DWORD*)(lpCmd + 1); } return 0L; _____
Modified: trunk/reactos/lib/winmm/time.c --- trunk/reactos/lib/winmm/time.c 2005-03-15 21:39:07 UTC (rev 14105) +++ trunk/reactos/lib/winmm/time.c 2005-03-15 21:44:42 UTC (rev 14106) @@ -408,9 +408,19 @@
{ TRACE("(%p, %u)\n", lpCaps, wSize);
+ if (lpCaps == 0) { + WARN("invalid lpCaps\n"); + return TIMERR_NOCANDO; + } + + if (wSize < sizeof(TIMECAPS)) { + WARN("invalid wSize\n"); + return TIMERR_NOCANDO; + } + lpCaps->wPeriodMin = MMSYSTIME_MININTERVAL; lpCaps->wPeriodMax = MMSYSTIME_MAXINTERVAL; - return 0; + return TIMERR_NOERROR; }
/*********************************************************************** *** _____
Modified: trunk/reactos/lib/winmm/wavemap/wavemap.c --- trunk/reactos/lib/winmm/wavemap/wavemap.c 2005-03-15 21:39:07 UTC (rev 14105) +++ trunk/reactos/lib/winmm/wavemap/wavemap.c 2005-03-15 21:44:42 UTC (rev 14106) @@ -62,6 +62,9 @@
/* ratio to compute position from a PCM playback to any format */ DWORD avgSpeedOuter; DWORD avgSpeedInner; + /* channel size of inner and outer */ + DWORD nSamplesPerSecOuter; + DWORD nSamplesPerSecInner; } WAVEMAPDATA;
static BOOL WAVEMAP_IsData(WAVEMAPDATA* wm) @@ -177,6 +180,7 @@ wom->dwClientInstance = lpDesc->dwInstance; wom->u.out.hOuterWave = (HWAVEOUT)lpDesc->hWave; wom->avgSpeedOuter = wom->avgSpeedInner = lpDesc->lpFormat->nAvgBytesPerSec; + wom->nSamplesPerSecOuter = wom->nSamplesPerSecInner = lpDesc->lpFormat->nSamplesPerSec;
for (i = ndlo; i < ndhi; i++) { /* if no ACM stuff is involved, no need to handle callbacks at this @@ -198,7 +202,7 @@
#define TRY(sps,bps) wfx.nSamplesPerSec = (sps); wfx.wBitsPerSample = (bps); \ switch (res=wodOpenHelper(wom, i, lpDesc, &wfx, dwFlags | WAVE_FORMAT_DIRECT)) { \ - case MMSYSERR_NOERROR: wom->avgSpeedInner = wfx.nAvgBytesPerSec; goto found; \ + case MMSYSERR_NOERROR: wom->avgSpeedInner = wfx.nAvgBytesPerSec; wom->nSamplesPerSecInner = wfx.nSamplesPerSec; goto found; \ case WAVERR_BADFORMAT: break; \ default: goto error; \ } @@ -414,12 +418,59 @@ static DWORD wodGetPosition(WAVEMAPDATA* wom, LPMMTIME lpTime, DWORD dwParam2) { DWORD val; + MMTIME timepos; TRACE("(%p %p %08lx)\n", wom, lpTime, dwParam2);
- val = waveOutGetPosition(wom->u.out.hInnerWave, lpTime, dwParam2); - if (lpTime->wType == TIME_BYTES) - lpTime->u.cb = MulDiv(lpTime->u.cb, wom->avgSpeedOuter, wom->avgSpeedInner); - /* other time types don't require conversion */ + memcpy(&timepos, lpTime, sizeof(timepos)); + + /* For TIME_MS, we're going to recalculate using TIME_BYTES */ + if (lpTime->wType == TIME_MS) + timepos.wType = TIME_BYTES; + + val = waveOutGetPosition(wom->u.out.hInnerWave, &timepos, dwParam2); + + if (lpTime->wType == TIME_BYTES || lpTime->wType == TIME_MS) + { + DWORD dwInnerSamplesPerOuter = wom->nSamplesPerSecInner / wom->nSamplesPerSecOuter; + if (dwInnerSamplesPerOuter > 0) + { + DWORD dwInnerBytesPerSample = wom->avgSpeedInner / wom->nSamplesPerSecInner; + DWORD dwInnerBytesPerOuterSample = dwInnerBytesPerSample * dwInnerSamplesPerOuter; + DWORD remainder = 0; + + /* If we are up sampling (going from lower sample rate to higher), + ** we need to make a special accomodation for times when we've + ** written a partial output sample. This happens frequently + ** to us because we use msacm to do our up sampling, and it + ** will up sample on an unaligned basis. + ** For example, if you convert a 2 byte wide 8,000 'outer' + ** buffer to a 2 byte wide 48,000 inner device, you would + ** expect 2 bytes of input to produce 12 bytes of output. + ** Instead, msacm will produce 8 bytes of output. + ** But reporting our position as 1 byte of output is + ** nonsensical; the output buffer position needs to be + ** aligned on outer sample size, and aggressively rounded up. + */ + remainder = timepos.u.cb % dwInnerBytesPerOuterSample; + if (remainder > 0) + { + timepos.u.cb -= remainder; + timepos.u.cb += dwInnerBytesPerOuterSample; + } + } + + lpTime->u.cb = MulDiv(timepos.u.cb, wom->avgSpeedOuter, wom->avgSpeedInner); + + /* Once we have the TIME_BYTES right, we can easily convert to TIME_MS */ + if (lpTime->wType == TIME_MS) + lpTime->u.cb = MulDiv(lpTime->u.cb, 1000, wom->avgSpeedOuter); + } + else if (lpTime->wType == TIME_SAMPLES) + lpTime->u.cb = MulDiv(timepos.u.cb, wom->nSamplesPerSecOuter, wom->nSamplesPerSecInner); + else + /* other time types don't require conversion */ + lpTime->u = timepos.u; + return val; }
@@ -691,6 +742,7 @@ }
wim->avgSpeedOuter = wim->avgSpeedInner = lpDesc->lpFormat->nAvgBytesPerSec; + wim->nSamplesPerSecOuter = wim->nSamplesPerSecInner = lpDesc->lpFormat->nSamplesPerSec;
for (i = ndlo; i < ndhi; i++) { if (waveInOpen(&wim->u.in.hInnerWave, i, lpDesc->lpFormat, (DWORD)widCallback, @@ -710,7 +762,7 @@
#define TRY(sps,bps) wfx.nSamplesPerSec = (sps); wfx.wBitsPerSample = (bps); \ switch (res=widOpenHelper(wim, i, lpDesc, &wfx, dwFlags | WAVE_FORMAT_DIRECT)) { \ - case MMSYSERR_NOERROR: wim->avgSpeedInner = wfx.nAvgBytesPerSec; goto found; \ + case MMSYSERR_NOERROR: wim->avgSpeedInner = wfx.nAvgBytesPerSec; wim->nSamplesPerSecInner = wfx.nSamplesPerSec; goto found; \ case WAVERR_BADFORMAT: break; \ default: goto error; \ } @@ -915,6 +967,8 @@ val = waveInGetPosition(wim->u.in.hInnerWave, lpTime, dwParam2); if (lpTime->wType == TIME_BYTES) lpTime->u.cb = MulDiv(lpTime->u.cb, wim->avgSpeedOuter, wim->avgSpeedInner); + if (lpTime->wType == TIME_SAMPLES) + lpTime->u.cb = MulDiv(lpTime->u.cb, wim->nSamplesPerSecOuter, wim->nSamplesPerSecInner); /* other time types don't require conversion */ return val; } _____
Modified: trunk/reactos/lib/winmm/winmm_Es.rc --- trunk/reactos/lib/winmm/winmm_Es.rc 2005-03-15 21:39:07 UTC (rev 14105) +++ trunk/reactos/lib/winmm/winmm_Es.rc 2005-03-15 21:44:42 UTC (rev 14106) @@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_DEFAULT +STRINGTABLE LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL BEGIN
/* MMSYS errors */