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 */