winealsa 24/32 bit sample size and 4/6 channel support

Robert Reif reif at earthlink.net
Wed Aug 18 18:43:48 CDT 2004


Adds 24/32 bit sample size and 4/6 channel support.
Adds dsound capture wine specific message support.
-------------- next part --------------
Index: dlls/winmm/winealsa/audio.c
===================================================================
RCS file: /home/wine/wine/dlls/winmm/winealsa/audio.c,v
retrieving revision 1.50
diff -u -r1.50 audio.c
--- dlls/winmm/winealsa/audio.c	12 Aug 2004 23:00:52 -0000	1.50
+++ dlls/winmm/winealsa/audio.c	18 Aug 2004 23:36:45 -0000
@@ -52,8 +52,12 @@
 #include "winnls.h"
 #include "winreg.h"
 #include "mmddk.h"
+#include "mmreg.h"
 #include "dsound.h"
 #include "dsdriver.h"
+#include "ks.h"
+#include "ksguid.h"
+#include "ksmedia.h"
 #define ALSA_PCM_NEW_HW_PARAMS_API
 #define ALSA_PCM_NEW_SW_PARAMS_API
 #include "alsa.h"
@@ -145,7 +149,7 @@
     volatile int		state;			/* one of the WINE_WS_ manifest constants */
     WAVEOPENDESC		waveDesc;
     WORD			wFlags;
-    PCMWAVEFORMAT		format;
+    WAVEFORMATPCMEX		format;
     WAVEOUTCAPSA		caps;
 
     /* ALSA information (ALSA 0.9/1.x uses two different devices for playback/capture) */
@@ -192,7 +196,7 @@
     volatile int		state;			/* one of the WINE_WS_ manifest constants */
     WAVEOPENDESC		waveDesc;
     WORD			wFlags;
-    PCMWAVEFORMAT		format;
+    WAVEFORMATPCMEX		format;
     WAVEOUTCAPSA		caps;
 
     /* ALSA information (ALSA 0.9/1.x uses two different devices for playback/capture) */
@@ -244,48 +248,54 @@
 static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid);
 
 /* These strings used only for tracing */
-#if 1
-static const char *wodPlayerCmdString[] = {
-    "WINE_WM_PAUSING",
-    "WINE_WM_RESTARTING",
-    "WINE_WM_RESETTING",
-    "WINE_WM_HEADER",
-    "WINE_WM_UPDATE",
-    "WINE_WM_BREAKLOOP",
-    "WINE_WM_CLOSING",
-    "WINE_WM_STARTING",
-    "WINE_WM_STOPPING",
-};
-#endif
+static const char * getCmdString(enum win_wm_message msg)
+{
+    static char unknown[32];
+#define MSG_TO_STR(x) case x: return #x
+    switch(msg) {
+    MSG_TO_STR(WINE_WM_PAUSING);
+    MSG_TO_STR(WINE_WM_RESTARTING);
+    MSG_TO_STR(WINE_WM_RESETTING);
+    MSG_TO_STR(WINE_WM_HEADER);
+    MSG_TO_STR(WINE_WM_UPDATE);
+    MSG_TO_STR(WINE_WM_BREAKLOOP);
+    MSG_TO_STR(WINE_WM_CLOSING);
+    MSG_TO_STR(WINE_WM_STARTING);
+    MSG_TO_STR(WINE_WM_STOPPING);
+    }
+#undef MSG_TO_STR
+    sprintf(unknown, "UNKNOWN(0x%08x)", msg);
+    return unknown;
+}
 
 static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
-                             PCMWAVEFORMAT* format)
+                             WAVEFORMATPCMEX* 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);
+          lpTime->wType, format->Format.wBitsPerSample, format->Format.nSamplesPerSec,
+          format->Format.nChannels, format->Format.nAvgBytesPerSec);
     TRACE("Position in bytes=%lu\n", position);
 
     switch (lpTime->wType) {
     case TIME_SAMPLES:
-        lpTime->u.sample = position / (format->wBitsPerSample / 8 * format->wf.nChannels);
+        lpTime->u.sample = position / (format->Format.wBitsPerSample / 8 * format->Format.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);
+        lpTime->u.ms = 1000.0 * position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels * format->Format.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;
+        position = position / (format->Format.wBitsPerSample / 8 * format->Format.nChannels);
+        lpTime->u.smpte.sec = position / format->Format.nSamplesPerSec;
+        position -= lpTime->u.smpte.sec * format->Format.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;
+        lpTime->u.smpte.frame = position * lpTime->u.smpte.fps / format->Format.nSamplesPerSec;
+        position -= lpTime->u.smpte.frame * format->Format.nSamplesPerSec / lpTime->u.smpte.fps;
         if (position != 0)
         {
             /* Round up */
@@ -307,6 +317,61 @@
     return MMSYSERR_NOERROR;
 }
 
+static BOOL supportedFormat(LPWAVEFORMATEX wf)
+{
+    TRACE("(%p)\n",wf);
+
+    if (wf->nSamplesPerSec<DSBFREQUENCY_MIN||wf->nSamplesPerSec>DSBFREQUENCY_MAX)
+        return FALSE;
+
+    if (wf->wFormatTag == WAVE_FORMAT_PCM) {
+        if (wf->nChannels==1||wf->nChannels==2) {
+            if (wf->wBitsPerSample==8||wf->wBitsPerSample==16)
+                return TRUE;
+        }
+    } else if (wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
+        WAVEFORMATEXTENSIBLE 	* wfex = (WAVEFORMATEXTENSIBLE *)wf;
+
+        if (wf->cbSize == 22 && IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) {
+            if (wf->nChannels>=1 && wf->nChannels<=6) {
+                if (wf->wBitsPerSample==wfex->Samples.wValidBitsPerSample) {
+                    if (wf->wBitsPerSample==8||wf->wBitsPerSample==16||
+                        wf->wBitsPerSample==24||wf->wBitsPerSample==32) {
+                        return TRUE;
+                    }
+                } else
+                    WARN("wBitsPerSample != wValidBitsPerSample not supported yet\n");
+            }
+        } else
+            WARN("only KSDATAFORMAT_SUBTYPE_PCM supported\n");
+    } else if (wf->wFormatTag == WAVE_FORMAT_MULAW || wf->wFormatTag == WAVE_FORMAT_ALAW) {
+        if (wf->wBitsPerSample==8)
+            return TRUE;
+        else
+            ERR("WAVE_FORMAT_MULAW and WAVE_FORMAT_ALAW wBitsPerSample must = 8\n");
+
+    } else if (wf->wFormatTag == WAVE_FORMAT_ADPCM) {
+        if (wf->wBitsPerSample==4)
+            return TRUE;
+        else
+            ERR("WAVE_FORMAT_ADPCM wBitsPerSample must = 4\n");
+    } else
+        WARN("only WAVE_FORMAT_PCM and WAVE_FORMAT_EXTENSIBLE supported\n");
+
+    return FALSE;
+}
+
+static void copy_format(LPWAVEFORMATEX wf1, LPWAVEFORMATPCMEX wf2)
+{
+    ZeroMemory(wf2, sizeof(wf2));
+    if (wf1->wFormatTag == WAVE_FORMAT_PCM)
+        memcpy(wf2, wf1, sizeof(PCMWAVEFORMAT));
+    else if (wf1->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
+        memcpy(wf2, wf1, sizeof(WAVEFORMATPCMEX));
+    else
+        memcpy(wf2, wf1, sizeof(WAVEFORMATEX) + wf1->cbSize);
+}
+
 /*======================================================================*
  *                  Low level WAVE implementation			*
  *======================================================================*/
@@ -717,7 +782,7 @@
     }
 
     if ( chmin > 1) FIXME("-\n");
-    wwo->caps.wChannels = (chmax >= 2) ? 2 : 1;
+    wwo->caps.wChannels = chmax;
     if (chmin <= 2 && 2 <= chmax)
         wwo->caps.dwSupport |= WAVECAPS_LRVOLUME;
 
@@ -826,7 +891,7 @@
     }
 
     if ( chmin > 1) FIXME("-\n");
-    wwi->caps.wChannels = (chmax >= 2) ? 2 : 1;
+    wwi->caps.wChannels = chmax;
     if (chmin <= 2 && 2 <= chmax)
         wwi->caps.dwSupport |= WAVECAPS_LRVOLUME;
 
@@ -839,8 +904,11 @@
 	snd_pcm_hw_params_get_access_mask(hw_params, acmask);
 
 	/* FIXME: NONITERLEAVED and COMPLEX are not supported right now */
-	if ( snd_pcm_access_mask_test( acmask, SND_PCM_ACCESS_MMAP_INTERLEAVED ) )
+	if ( snd_pcm_access_mask_test( acmask, SND_PCM_ACCESS_MMAP_INTERLEAVED ) ) {
+#if 0
             wwi->caps.dwSupport |= WAVECAPS_DIRECTSOUND;
+#endif
+        }
     }
 
     TRACE("Configured with dwFmts=%08lx dwSupport=%08lx\n",
@@ -933,7 +1001,9 @@
             return 0;
         }
         if (omr->msg_toget != omr->msg_tosave && omr->messages[omr->msg_toget].msg != WINE_WM_HEADER)
-            FIXME("two fast messages in the queue!!!!\n");
+            FIXME("two fast messages in the queue!!!! toget = %d(%s), tosave=%d(%s)\n",
+                  omr->msg_toget,getCmdString(omr->messages[omr->msg_toget].msg),
+                  omr->msg_tosave,getCmdString(omr->messages[omr->msg_tosave].msg));
 
         /* fast messages have to be added at the start of the queue */
         omr->msg_toget = (omr->msg_toget + omr->ring_buffer_size - 1) % omr->ring_buffer_size;
@@ -1147,7 +1217,7 @@
     if (lpWaveHdr->reserved < wwo->dwPlayedTotal) {
         dwMillis = 1;
     } else {
-        dwMillis = (lpWaveHdr->reserved - wwo->dwPlayedTotal) * 1000 / wwo->format.wf.nAvgBytesPerSec;
+        dwMillis = (lpWaveHdr->reserved - wwo->dwPlayedTotal) * 1000 / wwo->format.Format.nAvgBytesPerSec;
         if (!dwMillis) dwMillis = 1;
     }
 
@@ -1342,7 +1412,7 @@
     int                 err;
 
     while (ALSA_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev)) {
-     TRACE("Received %s %lx\n", wodPlayerCmdString[msg - WM_USER - 1], param); 
+     TRACE("Received %s %lx\n", getCmdString(msg), param); 
 
 	switch (msg) {
 	case WINE_WM_PAUSING:
@@ -1520,7 +1590,7 @@
     snd_pcm_hw_params_t *       hw_params;
     snd_pcm_sw_params_t *       sw_params;
     snd_pcm_access_t            access;
-    snd_pcm_format_t            format;
+    snd_pcm_format_t            format = -1;
     unsigned int                rate;
     unsigned int                buffer_time = 500000;
     unsigned int                period_time = 10000;
@@ -1545,11 +1615,7 @@
     }
 
     /* only PCM format is supported so far... */
-    if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
-	lpDesc->lpFormat->nChannels == 0 ||
-	lpDesc->lpFormat->nSamplesPerSec < DSBFREQUENCY_MIN ||
-	lpDesc->lpFormat->nSamplesPerSec > DSBFREQUENCY_MAX ||
-        (lpDesc->lpFormat->wBitsPerSample!=8 && lpDesc->lpFormat->wBitsPerSample!=16)) {
+    if (!supportedFormat(lpDesc->lpFormat)) {
 	WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
 	     lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
 	     lpDesc->lpFormat->nSamplesPerSec);
@@ -1582,15 +1648,15 @@
 
     wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
 
-    memcpy(&wwo->waveDesc, lpDesc, 	     sizeof(WAVEOPENDESC));
-    memcpy(&wwo->format,   lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
+    memcpy(&wwo->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
+    copy_format(lpDesc->lpFormat, &wwo->format);
 
-    if (wwo->format.wBitsPerSample == 0) {
+    if (wwo->format.Format.wBitsPerSample == 0) {
 	WARN("Resetting zeroed wBitsPerSample\n");
-	wwo->format.wBitsPerSample = 8 *
-	    (wwo->format.wf.nAvgBytesPerSec /
-	     wwo->format.wf.nSamplesPerSec) /
-	    wwo->format.wf.nChannels;
+	wwo->format.Format.wBitsPerSample = 8 *
+	    (wwo->format.Format.nAvgBytesPerSec /
+	     wwo->format.Format.nSamplesPerSec) /
+	    wwo->format.Format.nChannels;
     }
 
     snd_pcm_hw_params_any(pcm, hw_params);
@@ -1616,21 +1682,45 @@
     else
 	wwo->write = snd_pcm_mmap_writei;
 
-    EXIT_ON_ERROR( snd_pcm_hw_params_set_channels(pcm, hw_params, wwo->format.wf.nChannels), MMSYSERR_INVALPARAM, "unable to set required channels");
+    EXIT_ON_ERROR( snd_pcm_hw_params_set_channels(pcm, hw_params, wwo->format.Format.nChannels), MMSYSERR_INVALPARAM, "unable to set required channels");
+
+    if ((wwo->format.Format.wFormatTag == WAVE_FORMAT_PCM) ||
+        ((wwo->format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) &&
+        IsEqualGUID(&wwo->format.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) {
+        format = (wwo->format.Format.wBitsPerSample == 8) ? SND_PCM_FORMAT_U8 :
+                 (wwo->format.Format.wBitsPerSample == 16) ? SND_PCM_FORMAT_S16_LE :
+                 (wwo->format.Format.wBitsPerSample == 24) ? SND_PCM_FORMAT_S24_LE :
+                 (wwo->format.Format.wBitsPerSample == 32) ? SND_PCM_FORMAT_S32_LE : -1;
+    } else if (wwo->format.Format.wFormatTag == WAVE_FORMAT_MULAW) {
+        FIXME("unimplemented format: WAVE_FORMAT_MULAW\n");
+        snd_pcm_close(pcm);
+        return WAVERR_BADFORMAT;
+    } else if (wwo->format.Format.wFormatTag == WAVE_FORMAT_ALAW) {
+        FIXME("unimplemented format: WAVE_FORMAT_ALAW\n");
+        snd_pcm_close(pcm);
+        return WAVERR_BADFORMAT;
+    } else if (wwo->format.Format.wFormatTag == WAVE_FORMAT_ADPCM) {
+        FIXME("unimplemented format: WAVE_FORMAT_ADPCM\n");
+        snd_pcm_close(pcm);
+        return WAVERR_BADFORMAT;
+    } else {
+        ERR("invalid format: %0x04x\n", wwo->format.Format.wFormatTag);
+        snd_pcm_close(pcm);
+        return WAVERR_BADFORMAT;
+    }
 
-    format = (wwo->format.wBitsPerSample == 16) ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_U8;
     EXIT_ON_ERROR( snd_pcm_hw_params_set_format(pcm, hw_params, format), MMSYSERR_INVALPARAM, "unable to set required format");
 
-    rate = wwo->format.wf.nSamplesPerSec;
+    rate = wwo->format.Format.nSamplesPerSec;
     dir=0;
     err = snd_pcm_hw_params_set_rate_near(pcm, hw_params, &rate, &dir);
     if (err < 0) {
-	ERR("Rate %ld Hz not available for playback: %s\n", wwo->format.wf.nSamplesPerSec, snd_strerror(rate));
+	ERR("Rate %ld Hz not available for playback: %s\n", wwo->format.Format.nSamplesPerSec, snd_strerror(rate));
 	snd_pcm_close(pcm);
         return WAVERR_BADFORMAT;
     }
-    if (rate != wwo->format.wf.nSamplesPerSec) {
-	ERR("Rate doesn't match (requested %ld Hz, got %d Hz)\n", wwo->format.wf.nSamplesPerSec, rate);
+    if (rate != wwo->format.Format.nSamplesPerSec) {
+	ERR("Rate doesn't match (requested %ld Hz, got %d Hz)\n", wwo->format.Format.nSamplesPerSec, rate);
 	snd_pcm_close(pcm);
         return WAVERR_BADFORMAT;
     }
@@ -1700,13 +1790,13 @@
     wwo->hStartUpEvent = INVALID_HANDLE_VALUE;
 
     TRACE("handle=%08lx \n", (DWORD)wwo->p_handle);
-/*    if (wwo->dwFragmentSize % wwo->format.wf.nBlockAlign)
+/*    if (wwo->dwFragmentSize % wwo->format.Format.nBlockAlign)
 	ERR("Fragment doesn't contain an integral number of data blocks\n");
 */
     TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
-	  wwo->format.wBitsPerSample, wwo->format.wf.nAvgBytesPerSec,
-	  wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,
-	  wwo->format.wf.nBlockAlign);
+	  wwo->format.Format.wBitsPerSample, wwo->format.Format.nAvgBytesPerSec,
+	  wwo->format.Format.nSamplesPerSec, wwo->format.Format.nChannels,
+	  wwo->format.Format.nBlockAlign);
 
     return wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);
 }
@@ -2748,7 +2838,7 @@
     SetEvent(wwi->hStartUpEvent);
 
     /* make sleep time to be # of ms to output a period */
-    dwSleepTime = (1024/*wwi-dwPeriodSize => overrun!*/ * 1000) / wwi->format.wf.nAvgBytesPerSec;
+    dwSleepTime = (1024/*wwi-dwPeriodSize => overrun!*/ * 1000) / wwi->format.Format.nAvgBytesPerSec;
     frames_per_period = snd_pcm_bytes_to_frames(wwi->p_handle, wwi->dwPeriodSize); 
     TRACE("sleeptime=%ld ms\n", dwSleepTime);
 
@@ -2803,6 +2893,10 @@
 			    widNotifyClient(wwi, WIM_DATA, (DWORD)lpWaveHdr, 0);
 			    lpWaveHdr = lpNext;
 			}
+                    } else {
+                        TRACE("read(%s, %p, %ld) failed (%s)\n", wwi->device,
+                            lpWaveHdr->lpData + lpWaveHdr->dwBytesRecorded,
+                            frames_per_period, strerror(errno));
                     }
                 }
 		else
@@ -2814,6 +2908,12 @@
 
                     TRACE("bytesRead=%ld (local)\n", bytesRead);
 
+		    if (bytesRead == (DWORD) -1) {
+			TRACE("read(%s, %p, %ld) failed (%s)\n", wwi->device,
+			      buffer, frames_per_period, strerror(errno));
+			continue;
+		    }	
+
                     /* copy data in client buffers */
                     while (bytesRead != (DWORD) -1 && bytesRead > 0)
                     {
@@ -2853,7 +2953,7 @@
 					LPWAVEHDR hdr;
 					ALSA_RetrieveRingMessage(&wwi->msgRing, &msg, &param, &ev);
 					hdr = ((LPWAVEHDR)param);
-					TRACE("msg = %s, hdr = %p, ev = %p\n", wodPlayerCmdString[msg - WM_USER - 1], hdr, ev);
+					TRACE("msg = %s, hdr = %p, ev = %p\n", getCmdString(msg), hdr, ev);
 					hdr->lpNext = 0;
 					if (lpWaveHdr == 0) {
 					    /* new head of queue */
@@ -2887,7 +2987,7 @@
 
 	while (ALSA_RetrieveRingMessage(&wwi->msgRing, &msg, &param, &ev))
 	{
-            TRACE("msg=%s param=0x%lx\n", wodPlayerCmdString[msg - WM_USER - 1], param);
+            TRACE("msg=%s param=0x%lx\n", getCmdString(msg), param);
 	    switch (msg) {
 	    case WINE_WM_PAUSING:
 		wwi->state = WINE_WS_PAUSED;
@@ -3012,11 +3112,7 @@
     }
 
     /* only PCM format is supported so far... */
-    if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||
-	lpDesc->lpFormat->nChannels == 0 ||
-	lpDesc->lpFormat->nSamplesPerSec < DSBFREQUENCY_MIN ||
-	lpDesc->lpFormat->nSamplesPerSec > DSBFREQUENCY_MAX ||
-        (lpDesc->lpFormat->wBitsPerSample!=8 && lpDesc->lpFormat->wBitsPerSample!=16)) {
+    if (!supportedFormat(lpDesc->lpFormat)) {
 	WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",
 	     lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
 	     lpDesc->lpFormat->nSamplesPerSec);
@@ -3049,15 +3145,15 @@
 
     wwi->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
 
-    memcpy(&wwi->waveDesc, lpDesc, 	     sizeof(WAVEOPENDESC));
-    memcpy(&wwi->format,   lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
+    memcpy(&wwi->waveDesc, lpDesc, sizeof(WAVEOPENDESC));
+    copy_format(lpDesc->lpFormat, &wwi->format);
 
-    if (wwi->format.wBitsPerSample == 0) {
+    if (wwi->format.Format.wBitsPerSample == 0) {
 	WARN("Resetting zeroed wBitsPerSample\n");
-	wwi->format.wBitsPerSample = 8 *
-	    (wwi->format.wf.nAvgBytesPerSec /
-	     wwi->format.wf.nSamplesPerSec) /
-	    wwi->format.wf.nChannels;
+	wwi->format.Format.wBitsPerSample = 8 *
+	    (wwi->format.Format.nAvgBytesPerSec /
+	     wwi->format.Format.nSamplesPerSec) /
+	    wwi->format.Format.nChannels;
     }
 
     snd_pcm_hw_params_any(pcm, hw_params);
@@ -3083,21 +3179,45 @@
     else
 	wwi->read = snd_pcm_mmap_readi;
 
-    EXIT_ON_ERROR( snd_pcm_hw_params_set_channels(pcm, hw_params, wwi->format.wf.nChannels), MMSYSERR_INVALPARAM, "unable to set required channels");
+    EXIT_ON_ERROR( snd_pcm_hw_params_set_channels(pcm, hw_params, wwi->format.Format.nChannels), MMSYSERR_INVALPARAM, "unable to set required channels");
+
+    if ((wwi->format.Format.wFormatTag == WAVE_FORMAT_PCM) ||
+        ((wwi->format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) &&
+        IsEqualGUID(&wwi->format.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) {
+        format = (wwi->format.Format.wBitsPerSample == 8) ? SND_PCM_FORMAT_U8 :
+                 (wwi->format.Format.wBitsPerSample == 16) ? SND_PCM_FORMAT_S16_LE :
+                 (wwi->format.Format.wBitsPerSample == 24) ? SND_PCM_FORMAT_S24_LE :
+                 (wwi->format.Format.wBitsPerSample == 32) ? SND_PCM_FORMAT_S32_LE : -1;
+    } else if (wwi->format.Format.wFormatTag == WAVE_FORMAT_MULAW) {
+        FIXME("unimplemented format: WAVE_FORMAT_MULAW\n");
+        snd_pcm_close(pcm);
+        return WAVERR_BADFORMAT;
+    } else if (wwi->format.Format.wFormatTag == WAVE_FORMAT_ALAW) {
+        FIXME("unimplemented format: WAVE_FORMAT_ALAW\n");
+        snd_pcm_close(pcm);
+        return WAVERR_BADFORMAT;
+    } else if (wwi->format.Format.wFormatTag == WAVE_FORMAT_ADPCM) {
+        FIXME("unimplemented format: WAVE_FORMAT_ADPCM\n");
+        snd_pcm_close(pcm);
+        return WAVERR_BADFORMAT;
+    } else {
+        ERR("invalid format: %0x04x\n", wwi->format.Format.wFormatTag);
+        snd_pcm_close(pcm);
+        return WAVERR_BADFORMAT;
+    }
 
-    format = (wwi->format.wBitsPerSample == 16) ? SND_PCM_FORMAT_S16_LE : SND_PCM_FORMAT_U8;
     EXIT_ON_ERROR( snd_pcm_hw_params_set_format(pcm, hw_params, format), MMSYSERR_INVALPARAM, "unable to set required format");
 
-    rate = wwi->format.wf.nSamplesPerSec;
+    rate = wwi->format.Format.nSamplesPerSec;
     dir = 0;
     err = snd_pcm_hw_params_set_rate_near(pcm, hw_params, &rate, &dir);
     if (err < 0) {
-	ERR("Rate %ld Hz not available for playback: %s\n", wwi->format.wf.nSamplesPerSec, snd_strerror(rate));
+	ERR("Rate %ld Hz not available for playback: %s\n", wwi->format.Format.nSamplesPerSec, snd_strerror(rate));
 	snd_pcm_close(pcm);
         return WAVERR_BADFORMAT;
     }
-    if (rate != wwi->format.wf.nSamplesPerSec) {
-	ERR("Rate doesn't match (requested %ld Hz, got %d Hz)\n", wwi->format.wf.nSamplesPerSec, rate);
+    if (rate != wwi->format.Format.nSamplesPerSec) {
+	ERR("Rate doesn't match (requested %ld Hz, got %d Hz)\n", wwi->format.Format.nSamplesPerSec, rate);
 	snd_pcm_close(pcm);
         return WAVERR_BADFORMAT;
     }
@@ -3156,14 +3276,14 @@
     }
 
     wwi->dwPeriodSize = period_size;
-    /*if (wwi->dwFragmentSize % wwi->format.wf.nBlockAlign)
+    /*if (wwi->dwFragmentSize % wwi->format.Format.nBlockAlign)
 	ERR("Fragment doesn't contain an integral number of data blocks\n");
     */
     TRACE("dwPeriodSize=%lu\n", wwi->dwPeriodSize);
     TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",
-	  wwi->format.wBitsPerSample, wwi->format.wf.nAvgBytesPerSec,
-	  wwi->format.wf.nSamplesPerSec, wwi->format.wf.nChannels,
-	  wwi->format.wf.nBlockAlign);
+	  wwi->format.Format.wBitsPerSample, wwi->format.Format.nAvgBytesPerSec,
+	  wwi->format.Format.nSamplesPerSec, wwi->format.Format.nChannels,
+	  wwi->format.Format.nBlockAlign);
 
     if (!(dwFlags & WAVE_DIRECTSOUND)) {
 	wwi->hStartUpEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
@@ -3349,13 +3469,17 @@
 {
     WINE_WAVEIN*	wwi;
 
-    FIXME("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
+    TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);
 
     if (wDevID >= MAX_WAVEINDRV || WInDev[wDevID].state == WINE_WS_CLOSED) {
 	WARN("can't get pos !\n");
 	return MMSYSERR_INVALHANDLE;
     }
-    if (lpTime == NULL)	return MMSYSERR_INVALPARAM;
+
+    if (lpTime == NULL)	{
+        WARN("invalid parameter: lpTime = NULL\n");
+        return MMSYSERR_INVALPARAM;
+    }
 
     wwi = &WInDev[wDevID];
     ALSA_AddRingMessage(&wwi->msgRing, WINE_WM_UPDATE, 0, TRUE);
@@ -3377,7 +3501,7 @@
 static DWORD widDevInterfaceSize(UINT wDevID, LPDWORD dwParam1)
 {
     TRACE("(%u, %p)\n", wDevID, dwParam1);
-                                                                                                                                             
+
     *dwParam1 = MultiByteToWideChar(CP_ACP, 0, WInDev[wDevID].interface_name, -1,
                                     NULL, 0 ) * sizeof(WCHAR);
     return MMSYSERR_NOERROR;
@@ -3399,6 +3523,40 @@
 }
 
 /**************************************************************************
+ *                              widDsCreate                     [internal]
+ */
+static DWORD widDsCreate(UINT wDevID, PIDSCDRIVER* drv)
+{
+    TRACE("(%d,%p)\n",wDevID,drv);
+
+    /* the HAL isn't much better than the HEL if we can't do mmap() */
+    FIXME("DirectSoundCapture not implemented\n");
+    MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");
+    return MMSYSERR_NOTSUPPORTED;
+}
+
+/**************************************************************************
+ *                              widDsDesc                       [internal]
+ */
+static DWORD widDsDesc(UINT wDevID, PDSDRIVERDESC desc)
+{
+    memcpy(desc, &(WInDev[wDevID].ds_desc), sizeof(DSDRIVERDESC));
+    return MMSYSERR_NOERROR;
+}
+
+/**************************************************************************
+ *                              widDsGuid                       [internal]
+ */
+static DWORD widDsGuid(UINT wDevID, LPGUID pGuid)
+{
+    TRACE("(%d,%p)\n",wDevID,pGuid);
+
+    memcpy(pGuid, &(WInDev[wDevID].ds_guid), sizeof(GUID));
+
+    return MMSYSERR_NOERROR;
+}
+
+/**************************************************************************
  * 				widMessage (WINEALSA.@)
  */
 DWORD WINAPI ALSA_widMessage(UINT wDevID, UINT wMsg, DWORD dwUser,
@@ -3427,9 +3585,9 @@
     case WIDM_STOP: 		return widStop	(wDevID, (LPWAVEHDR)dwParam1, 		dwParam2);
     case DRV_QUERYDEVICEINTERFACESIZE: return widDevInterfaceSize       (wDevID, (LPDWORD)dwParam1);
     case DRV_QUERYDEVICEINTERFACE:     return widDevInterface           (wDevID, (PWCHAR)dwParam1, dwParam2);
-    /*case DRV_QUERYDSOUNDIFACE:	return widDsCreate   (wDevID, (PIDSCDRIVER*)dwParam1);
+    case DRV_QUERYDSOUNDIFACE:	return widDsCreate   (wDevID, (PIDSCDRIVER*)dwParam1);
     case DRV_QUERYDSOUNDDESC:	return widDsDesc     (wDevID, (PDSDRIVERDESC)dwParam1);
-    case DRV_QUERYDSOUNDGUID:	return widDsGuid     (wDevID, (LPGUID)dwParam1);*/
+    case DRV_QUERYDSOUNDGUID:	return widDsGuid     (wDevID, (LPGUID)dwParam1);
     default:
 	FIXME("unknown message %d!\n", wMsg);
     }


More information about the wine-patches mailing list