[DSOUND] Implement a locking mechanism

Maarten Lankhorst m.b.lankhorst at gmail.com
Wed Feb 21 13:27:17 CST 2007


[DSOUND] Implement a locking mechanism

Attempt to implement locking in dsounds mixer.

Sadly horribly broken, I'm posting this in the hope someone knows what
magic values to fill in at the first "if (lock)" .. I really have no clue.

As stated before it is required to be used with previous winealsa patch.

Right now it also calls Unlock with lockamount as argument, this should
probably be changed to how much is actually written to (frag), but that
part doesn't really matter much I think, it's more important to get the
first Lock() right.
-------------- next part --------------
>From df89b6b066720cad1c97ca30975ad7a2adf1bc1d Mon Sep 17 00:00:00 2001
From: maarten <maarten at maarten-laptop.(none)>
Date: Wed, 21 Feb 2007 20:11:50 +0100
Subject: [PATCH] Attempting to implement lock in dsounds mixer
---
 dlls/dsound/mixer.c |   56 +++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 49 insertions(+), 7 deletions(-)

diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
index 77e98bb..17c57e6 100644
--- a/dlls/dsound/mixer.c
+++ b/dlls/dsound/mixer.c
@@ -1048,12 +1048,40 @@ static void DSOUND_PerformMix(DirectSoun
 	forced = ((device->state == STATE_PLAYING) || (device->state == STATE_STARTING));
 
 	if (device->priolevel != DSSCL_WRITEPRIMARY) {
+		/* Variables used:
+		 * paused: is playback paused?
+		 * lock: wether Lock() and Unlock() should be used for access
+		 * playpos: where the hardware is currently playing at
+		 * writepos: the position from where it is safe to write
+		 * inq: How much data is still in the queue
+		 * maxq: How much data can be queued at maximum
+		 * frag: How long a fragment is
+		 */
+		BOOL lock = device->hwbuf && !(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK);
 		BOOL paused = ((device->state == STATE_STOPPED) || (device->state == STATE_STARTING));
-		/* FIXME: document variables */
  		DWORD playpos, writepos, inq, maxq, frag;
- 		if (device->hwbuf) {
+		DWORD lockamount;
+		LPVOID lockbuf;
+		
+		if (lock) {
+			frag = device->fraglen * device->prebuf;
+			if (frag > device->buflen)
+				frag = device->buflen;
+
+			hres = IDsDriverBuffer_Lock(device->hwbuf, &lockbuf, &lockamount, NULL, NULL, /*FILL ME IN!!*/device->playpos, frag, 0);
+			if (FAILED(hres))
+			{
+				ERR("Can not lock a buffer for playback\n");
+				return;
+			}
+			writepos = ((DWORD)lockbuf - (DWORD)device->buffer);
+			playpos = writepos;
+			if (!paused) /* For nice sound.. */
+				/* I NEED SOMETHING SENSIBLE HERE SO SOUND WOULD WORK FOR ONCE */
+				playpos = (device->mixpos + lockamount - ds_hel_margin * device->fraglen)%device->buflen;
+		} else if (device->hwbuf) {
 			hres = IDsDriverBuffer_GetPosition(device->hwbuf, &playpos, &writepos);
-			if (hres) {
+			if (FAILED(hres)) {
 			    WARN("IDsDriverBuffer_GetPosition failed\n");
 			    return;
 			}
@@ -1106,10 +1134,12 @@ static void DSOUND_PerformMix(DirectSoun
 
 		/* check for consistency */
 		if (inq > maxq) {
+			if (lock)
+				IDsDriverBuffer_Unlock(device->hwbuf, lockbuf, 0, NULL, 0);
 			/* the playback position must have passed our last
 			 * mixed position, i.e. it's an underrun, or we have
 			 * nothing more to play */
-			TRACE("reached end of mixed data (inq=%d, maxq=%d)\n", inq, maxq);
+			ERR("reached end of mixed data (inq=%d, maxq=%d)\n", inq, maxq);
 			inq = 0;
 			/* stop the playback now, to allow buffers to refill */
 			if (device->state == STATE_PLAYING) {
@@ -1131,11 +1161,19 @@ #endif
 #ifdef SYNC_CALLBACK
 			EnterCriticalSection(&(device->mixlock));
 #endif
-			if (device->hwbuf) {
+			if (lock) {
+				hres = IDsDriverBuffer_Lock(device->hwbuf, &lockbuf, &lockamount, NULL, NULL, 0, device->buflen, 0);
+				if (FAILED(hres)) {
+					LeaveCriticalSection(&(device->mixlock));
+					WARN("IDsDriverBuffer_Lock failed: 0x%8d\n", hres);
+					return;
+				}
+				playpos = (DWORD)lockbuf - (DWORD)device->buffer;
+			} else if (device->hwbuf) {
 				/* the Stop is supposed to reset play position to beginning of buffer */
 				/* unfortunately, OSS is not able to do so, so get current pointer */
 				hres = IDsDriverBuffer_GetPosition(device->hwbuf, &playpos, NULL);
-				if (hres) {
+				if (FAILED(hres)) {
 					LeaveCriticalSection(&(device->mixlock));
 					WARN("IDsDriverBuffer_GetPosition failed\n");
 					return;
@@ -1155,10 +1193,14 @@ #endif
 
 		/* do the mixing */
 		frag = DSOUND_MixToPrimary(device, playpos, writepos, maxq, paused);
-		if (forced) frag = maxq - inq;
+		if (forced)
+			frag = maxq - inq;
 		device->mixpos += frag;
 		device->mixpos %= device->buflen;
 
+		if (lock)
+			IDsDriverBuffer_Unlock(device->hwbuf, lockbuf, lockamount, NULL, 0);
+
 		if (frag) {
 			/* buffers have been filled, restart playback */
 			if (device->state == STATE_STARTING) {
-- 
1.4.1



More information about the wine-patches mailing list