Francois Gouget : wineesd.drv: Let the EsounD server adjust the volume.

Alexandre Julliard julliard at winehq.org
Mon Mar 30 12:08:44 CDT 2009


Module: wine
Branch: master
Commit: 9e31d23e731c9e6d6eab9282f954f7a152dfefd5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9e31d23e731c9e6d6eab9282f954f7a152dfefd5

Author: Francois Gouget <fgouget at codeweavers.com>
Date:   Sat Mar 28 11:27:42 2009 +0100

wineesd.drv: Let the EsounD server adjust the volume.

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).

---

 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 d0eed60..e15b2fd 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;
 }




More information about the wine-cvs mailing list