[6/11] wineesd.drv: Let the EsounD server adjust the volume.

Francois Gouget fgouget at codeweavers.com
Sat Mar 28 05:27:42 CDT 2009


This simplifies our code and avoids data copying.
Also, now wodGetVolume() returns the real EsounD volume, even if it has been modified by an external mixer (e.g. esdctl).
---

Uses the unique name added in the previous patch.

 dlls/wineesd.drv/audio.c |  222 ++++++++++++++++++----------------------------
 1 files changed, 86 insertions(+), 136 deletions(-)

diff --git a/dlls/wineesd.drv/audio.c b/dlls/wineesd.drv/audio.c
index 024cfd5..7ef11c3 100644
--- a/dlls/wineesd.drv/audio.c
+++ b/dlls/wineesd.drv/audio.c
@@ -167,12 +167,8 @@ typedef struct {
     /* esd information */
     char*			stream_name;		/* a unique name identifying the esd stream */
     int				stream_fd;		/* the socket fd we get from esd when opening a stream for playing */
-
-    char*			sound_buffer;
-    long			buffer_size;
-
-    DWORD			volume_left;		/* volume control information */
-    DWORD			volume_right;
+    int				stream_id;		/* the stream id (to change the volume) */
+    int				esd_fd;			/* a socket to communicate with the sound server */
 
     LPWAVEHDR			lpQueuePtr;		/* start of queued WAVEHDRs (waiting to be notified) */
     LPWAVEHDR			lpPlayPtr;		/* start of not yet fully played buffers */
@@ -253,59 +249,6 @@ static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc)
  *                  Low level WAVE implementation			*
  *======================================================================*/
 
-/* Volume functions derived from Alsaplayer source */
-/* length is the number of 16 bit samples */
-static void volume_effect16(void *bufin, void* bufout, int length, int left,
-		int right, int 	nChannels)
-{
-  short *d_out = bufout;
-  short *d_in = bufin;
-  int i, v;
-
-/*
-  TRACE("length == %d, nChannels == %d\n", length, nChannels);
-*/
-
-  if (right == -1) right = left;
-
-  for(i = 0; i < length; i+=(nChannels))
-  {
-    v = (int) ((*(d_in++) * left) / 100);
-    *(d_out++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
-    if(nChannels == 2)
-    {
-      v = (int) ((*(d_in++) * right) / 100);
-      *(d_out++) = (v>32767) ? 32767 : ((v<-32768) ? -32768 : v);
-    }
-  }
-}
-
-/* length is the number of 8 bit samples */
-static void volume_effect8(void *bufin, void* bufout, int length, int left,
-		int right, int 	nChannels)
-{
-  BYTE *d_out = bufout;
-  BYTE *d_in = bufin;
-  int i, v;
-
-/*
-  TRACE("length == %d, nChannels == %d\n", length, nChannels);
-*/
-
-  if (right == -1) right = left;
-
-  for(i = 0; i < length; i+=(nChannels))
-  {
-    v = (BYTE) ((*(d_in++) * left) / 100);
-    *(d_out++) = (v>255) ? 255 : ((v<0) ? 0 : v);
-    if(nChannels == 2)
-    {
-      v = (BYTE) ((*(d_in++) * right) / 100);
-      *(d_out++) = (v>255) ? 255 : ((v<0) ? 0 : v);
-    }
-  }
-}
-
 static DWORD bytes_to_mmtime(LPMMTIME lpTime, DWORD position,
                              WAVEFORMATPCMEX* format)
 {
@@ -424,11 +367,8 @@ static void	ESD_CloseWaveOutDevice(WINE_WAVEOUT* wwo)
 	HeapFree(GetProcessHeap(), 0, wwo->stream_name);
 	esd_close(wwo->stream_fd);
 	wwo->stream_fd = -1;
-
-  /* free up the buffer we use for volume and reset the size */
-  HeapFree(GetProcessHeap(), 0, wwo->sound_buffer);
-  wwo->sound_buffer = NULL;
-  wwo->buffer_size = 0;
+	if (wwo->esd_fd)
+		esd_close(wwo->esd_fd);
 }
 
 /******************************************************************
@@ -847,56 +787,9 @@ static int wodPlayer_WriteMaxFrags(WINE_WAVEOUT* wwo, DWORD* bytes)
     TRACE("Writing wavehdr %p.%u[%u]\n",
           wwo->lpPlayPtr, wwo->dwPartialOffset, wwo->lpPlayPtr->dwBufferLength);
 
-    /* see if our buffer isn't large enough for the data we are writing */
-    if(wwo->buffer_size < toWrite)
-    {
-      if(wwo->sound_buffer)
-      {
-	wwo->sound_buffer = HeapReAlloc(GetProcessHeap(), 0, wwo->sound_buffer, toWrite);
-	wwo->buffer_size = toWrite;
-      }
-    }
-
-    /* if we don't have a buffer then get one */
-    if(!wwo->sound_buffer)
-    {
-      /* allocate some memory for the buffer */
-      wwo->sound_buffer = HeapAlloc(GetProcessHeap(), 0, toWrite);
-      wwo->buffer_size = toWrite;
-    }
-
-    /* if we don't have a buffer then error out */
-    if(!wwo->sound_buffer)
-    {
-      ERR("error allocating sound_buffer memory\n");
-      return 0;
-    }
-
-    TRACE("toWrite == %d\n", toWrite);
-
-    /* apply volume to the bits */
-    /* for single channel audio streams we only use the LEFT volume */
-    if(wwo->waveFormat.Format.wBitsPerSample == 16)
-    {
-      /* apply volume to the buffer we are about to send */
-      /* divide toWrite(bytes) by 2 as volume processes by 16 bits */
-      volume_effect16(wwo->lpPlayPtr->lpData + wwo->dwPartialOffset,
-                wwo->sound_buffer, toWrite>>1, wwo->volume_left,
-		wwo->volume_right, wwo->waveFormat.Format.nChannels);
-    } else if(wwo->waveFormat.Format.wBitsPerSample == 8)
-    {
-      /* apply volume to the buffer we are about to send */
-      volume_effect8(wwo->lpPlayPtr->lpData + wwo->dwPartialOffset,
-                wwo->sound_buffer, toWrite, wwo->volume_left,
-		wwo->volume_right, wwo->waveFormat.Format.nChannels);
-    } else
-    {
-      FIXME("unsupported wwo->format.wBitsPerSample of %d\n",
-        wwo->waveFormat.Format.wBitsPerSample);
-    }
-
     /* send the audio data to esd for playing */
-    written = write(wwo->stream_fd, wwo->sound_buffer, toWrite);
+    TRACE("toWrite == %d\n", toWrite);
+    written = write(wwo->stream_fd, wwo->lpPlayPtr->lpData + wwo->dwPartialOffset, toWrite);
 
     TRACE("written = %d\n", written);
 
@@ -1293,21 +1186,15 @@ static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
     wwo->stream_fd = esd_play_stream(out_format, out_rate, NULL, wwo->stream_name);
     TRACE("wwo->stream_fd=%d\n", wwo->stream_fd);
     if(wwo->stream_fd < 0) return MMSYSERR_ALLOCATED;
-    wwo->stream_name = get_stream_name("out", wDevID);
-
-    /* clear these so we don't have any confusion ;-) */
-    wwo->sound_buffer = 0;
-    wwo->buffer_size = 0;
 
+    wwo->stream_name = get_stream_name("out", wDevID);
+    wwo->stream_id = 0;
+    wwo->esd_fd = -1;
     wwo->dwPlayedTotal = 0;
     wwo->dwWrittenTotal = 0;
 
     wwo->dwSleepTime = (1024 * 1000 * BUFFER_REFILL_THRESHOLD) / wwo->waveFormat.Format.nAvgBytesPerSec;
 
-    /* Initialize volume to full level */
-    wwo->volume_left = 100;
-    wwo->volume_right = 100;
-
     ESD_InitRingMessage(&wwo->msgRing);
 
     /* create player thread */
@@ -1502,22 +1389,70 @@ static DWORD wodBreakLoop(WORD wDevID)
     return MMSYSERR_NOERROR;
 }
 
+static esd_player_info_t* wod_get_player(WINE_WAVEOUT* wwo, esd_info_t** esd_all_info)
+{
+    esd_player_info_t* player;
+
+    if (wwo->esd_fd == -1)
+    {
+        wwo->esd_fd = esd_open_sound(NULL);
+        if (wwo->esd_fd < 0)
+        {
+            WARN("esd_open_sound() failed (%d)\n", errno);
+            return NULL;
+        }
+    }
+
+    *esd_all_info = esd_get_all_info(wwo->esd_fd);
+    if (!*esd_all_info)
+    {
+        WARN("esd_get_all_info() failed (%d)\n", errno);
+        return NULL;
+    }
+
+    for (player = (*esd_all_info)->player_list; player != NULL; player = player->next)
+    {
+        if (strcmp(player->name, wwo->stream_name) == 0)
+        {
+            wwo->stream_id = player->source_id;
+            return player;
+        }
+    }
+
+    return NULL;
+}
+
 /**************************************************************************
  * 				wodGetVolume			[internal]
  */
 static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
 {
-    DWORD left, right;
-
-    left = WOutDev[wDevID].volume_left;
-    right = WOutDev[wDevID].volume_right;
+    esd_info_t* esd_all_info;
+    esd_player_info_t* player;
+    DWORD ret;
 
-    TRACE("(%u, %p);\n", wDevID, lpdwVol);
+    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].stream_fd == -1)
+    {
+	WARN("bad device ID !\n");
+	return MMSYSERR_BADDEVICEID;
+    }
 
-    *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<
-		16);
+    ret = MMSYSERR_ERROR;
+    player = wod_get_player(WOutDev+wDevID, &esd_all_info);
+    if (player)
+    {
+        DWORD left, right;
+        left = (player->left_vol_scale * 0xFFFF) / ESD_VOLUME_BASE;
+        right = (player->right_vol_scale * 0xFFFF) / ESD_VOLUME_BASE;
+        TRACE("volume = %u / %u\n", left, right);
+        *lpdwVol = left + (right << 16);
+        ret = MMSYSERR_NOERROR;
+    }
+    else
+        ret = MMSYSERR_ERROR;
 
-    return MMSYSERR_NOERROR;
+    esd_free_all_info(esd_all_info);
+    return ret;
 }
 
 /**************************************************************************
@@ -1525,15 +1460,30 @@ static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
  */
 static DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
 {
-    DWORD left, right;
+    WINE_WAVEOUT* wwo = WOutDev+wDevID;
 
-    left  = (LOWORD(dwParam) * 100) / 0xFFFFl;
-    right = (HIWORD(dwParam) * 100) / 0xFFFFl;
+    if (wDevID >= MAX_WAVEOUTDRV || wwo->stream_fd == -1)
+    {
+	WARN("bad device ID !\n");
+	return MMSYSERR_BADDEVICEID;
+    }
 
-    TRACE("(%u, %08X);\n", wDevID, dwParam);
+    /* stream_id is the ESD's file descriptor for our stream so it's should
+     * be non-zero if set.
+     */
+    if (!wwo->stream_id)
+    {
+        esd_info_t* esd_all_info;
+        /* wod_get_player sets the stream_id as a side effect */
+        wod_get_player(wwo, &esd_all_info);
+        esd_free_all_info(esd_all_info);
+    }
+    if (!wwo->stream_id)
+        return MMSYSERR_ERROR;
 
-    WOutDev[wDevID].volume_left = left;
-    WOutDev[wDevID].volume_right = right;
+    esd_set_stream_pan(wwo->esd_fd, wwo->stream_id,
+                       LOWORD(dwParam) * ESD_VOLUME_BASE / 0xFFFF,
+                       HIWORD(dwParam) * ESD_VOLUME_BASE / 0xFFFF);
 
     return MMSYSERR_NOERROR;
 }
-- 
1.6.2




More information about the wine-patches mailing list