[Sumover-dev] [svn commit] r3827 - rat/trunk

sumover-dev at cs.ucl.ac.uk sumover-dev at cs.ucl.ac.uk
Fri Sep 8 19:59:12 BST 2006


Author: piers
Date: Fri Sep  8 19:59:08 2006
New Revision: 3827

Modified:
   rat/trunk/auddev_win32.c

Log:
After comments from Robert Putnam on the AG-tech list I had a look at the callback handler - it is called by a separate thread spawned by the driver so with thread control it may be called at any time - leading to problems. I used the CRITICAL_SECTION routines to maintain exclusive access to key resources as needed in waveInProc() and w32sdk_audio_read(). Hopefully this has fixed a few random crashes for people...

Modified: rat/trunk/auddev_win32.c
==============================================================================
--- rat/trunk/auddev_win32.c	(original)
+++ rat/trunk/auddev_win32.c	Fri Sep  8 19:59:08 2006
@@ -37,7 +37,7 @@
 
 static int  error = 0;
 static char errorText[MAXERRORLENGTH];
-static int  nLoopGain = 0; /* Set 0 (from 100) as in AG version */
+static int  nLoopGain = 0;
 #define     MAX_DEV_NAME 64
 
 static UINT mapAudioDescToMixerID(audio_desc_t ad);
@@ -995,6 +995,8 @@
         return (whReadList != NULL);
 }
 
+CRITICAL_SECTION CriticalSection;    
+
 static void CALLBACK
 waveInProc(HWAVEIN hwi,
            UINT    uMsg,
@@ -1003,17 +1005,20 @@
            DWORD   dwParam2)
 {
         WAVEHDR *whRead, **whInsert;
-
         switch(uMsg) {
         case WIM_DATA:
+				EnterCriticalSection(&CriticalSection );
                 whRead = (WAVEHDR*)dwParam1;
-		/* Insert block at the available list */
+				/* Set lpNext of new audio data to NULL to mark end of 
+				   WAVEHDR whReadList linked list */
                 whRead->lpNext   = NULL;
-		whInsert = &whReadList;
+				whInsert = &whReadList;
+				/* Insert block at end of the whReadList list */
                 while(*whInsert != NULL) {
                         whInsert = &((*whInsert)->lpNext);
                 }
                 *whInsert = whRead;
+				LeaveCriticalSection(&CriticalSection );
                 SetEvent(hAudioReady);
 		break;
         default:
@@ -1026,12 +1031,17 @@
         return;
 }
 
+
+static int globalprobe;
+
 static int
 w32sdk_audio_open_in_probe(UINT uId, WAVEFORMATEX *pwfx, int probe)
 {
-        MMRESULT mmr;
+	    MMRESULT mmr;
         int      i;
 
+		globalprobe=probe;
+
         if (shWaveIn) {
 		return (TRUE);
 	}
@@ -1047,12 +1057,14 @@
 	}
         whReadHdrs = (WAVEHDR*)xmalloc(sizeof(WAVEHDR)*nblks);
         memset(whReadHdrs, 0, sizeof(WAVEHDR)*nblks);
-
+        if (!probe) {
+				InitializeCriticalSection(&CriticalSection);
+		}
         mmr = waveInOpen(&shWaveIn,
                          uId,
                          pwfx,
                          (DWORD)waveInProc,
-                         0,
+						 (probe ? 0 : (DWORD)&CriticalSection), 
                          (probe ? CALLBACK_NULL : CALLBACK_FUNCTION));
 
 	if (mmr != MMSYSERR_NOERROR) {
@@ -1063,27 +1075,27 @@
 
         if (!probe) {
           /* Initialize wave headers */
-	  for (i = 0; i < nblks; i++) {
-                whReadHdrs[i].lpData         = lpReadData + i * blksz;
-                whReadHdrs[i].dwBufferLength = blksz;
-                whReadHdrs[i].dwFlags        = 0;
-                mmr = waveInPrepareHeader(shWaveIn, &whReadHdrs[i], sizeof(WAVEHDR));
-                assert(mmr == MMSYSERR_NOERROR);
-                mmr = waveInAddBuffer(shWaveIn, &whReadHdrs[i], sizeof(WAVEHDR));
-                assert(mmr == MMSYSERR_NOERROR);
-	  }
-
-	  whReadList           = NULL;
-	  dwBytesUsedAtReadHead = 0;
-
-	  error = waveInStart(shWaveIn);
-	  if (error) {
-                waveInGetErrorText(error, errorText, sizeof(errorText));
-                debug_msg("Win32Audio: waveInStart: (%d) %s\n", error, errorText);
-                exit(1);
-	  }
-	  hAudioReady = CreateEvent(NULL, TRUE, FALSE, "RAT Audio Ready");
-        }
+			for (i = 0; i < nblks; i++) {
+						whReadHdrs[i].lpData         = lpReadData + i * blksz;
+						whReadHdrs[i].dwBufferLength = blksz;
+						whReadHdrs[i].dwFlags        = 0;
+						mmr = waveInPrepareHeader(shWaveIn, &whReadHdrs[i], sizeof(WAVEHDR));
+						assert(mmr == MMSYSERR_NOERROR);
+						mmr = waveInAddBuffer(shWaveIn, &whReadHdrs[i], sizeof(WAVEHDR));
+						assert(mmr == MMSYSERR_NOERROR);
+			}
+
+			whReadList           = NULL;
+			dwBytesUsedAtReadHead = 0;
+
+			error = waveInStart(shWaveIn);
+			if (error) {
+						waveInGetErrorText(error, errorText, sizeof(errorText));
+						debug_msg("Win32Audio: waveInStart: (%d) %s\n", error, errorText);
+						exit(1);
+			}
+			hAudioReady = CreateEvent(NULL, TRUE, FALSE, "RAT Audio Ready");
+		}
 
 	return (TRUE);
 }
@@ -1112,6 +1124,8 @@
         whReadList = NULL;
 
         waveInClose(shWaveIn);
+		if (!globalprobe) DeleteCriticalSection(&CriticalSection);
+
 	shWaveIn = 0;
 
 	xfree(whReadHdrs);
@@ -1127,47 +1141,49 @@
 w32sdk_audio_read(audio_desc_t ad, u_char *buf, int buf_bytes)
 {
         WAVEHDR *whCur;
-	MMRESULT mmr;
+		MMRESULT mmr;
         int done = 0, this_read;
-        static int added;
 
-	/* This is slightly ugle because we want to be able to operate when     */
+		/* This is slightly ugle because we want to be able to operate when     */
         /* buf_bytes has any value, not just a multiple of blksz.  In principle */
         /* we do this so the device blksz does not have to match application    */
         /* blksz.  I.e. can reduce process usage by using larger blocks at      */
         /* device whilst the app operates on smaller blocks.                    */
+		EnterCriticalSection(&CriticalSection );
 
         while(whReadList != NULL && done < buf_bytes) {
-		whCur = whReadList;
-		this_read = min((int)(whCur->dwBytesRecorded - dwBytesUsedAtReadHead), buf_bytes - done);
-                if (buf) {
-			memcpy(buf + done,
-			       whCur->lpData + dwBytesUsedAtReadHead,
-			       this_read);
-		}
-                done                  += this_read;
-                dwBytesUsedAtReadHead += this_read;
-                if (dwBytesUsedAtReadHead == whCur->dwBytesRecorded) {
-                        whReadList = whReadList->lpNext;
-			/* Finished with the block give it device */
-			assert(whCur->dwFlags & WHDR_DONE);
-			assert(whCur->dwFlags & ~WHDR_INQUEUE);
-                   	whCur->lpNext          = NULL;
-			whCur->dwBytesRecorded = 0;
-			whCur->dwFlags        &= ~WHDR_DONE;
-			mmr = waveInAddBuffer(shWaveIn, whCur, sizeof(WAVEHDR));
-                        assert(mmr == MMSYSERR_NOERROR);
-			/* PO-XXX: Commenting out as it appears to be too keen a check in some instances
-			   e.g. Some drivers aren't perfect.
-			assert(whCur->dwFlags & WHDR_INQUEUE);*/
-                        dwBytesUsedAtReadHead = 0;
-			added++;
-                }
-		assert((int)dwBytesUsedAtReadHead < blksz);
+			whCur = whReadList;
+			this_read = min((int)(whCur->dwBytesRecorded - dwBytesUsedAtReadHead), buf_bytes - done);
+			if (buf) {
+				memcpy(buf + done, whCur->lpData + dwBytesUsedAtReadHead, this_read);
+			}
+            done                  += this_read;
+            dwBytesUsedAtReadHead += this_read;
+            if (dwBytesUsedAtReadHead == whCur->dwBytesRecorded) {
+                whReadList = whReadList->lpNext;
+				/* Finished with the block give it device */
+				assert(whCur->dwFlags & WHDR_DONE);
+				assert(whCur->dwFlags & ~WHDR_INQUEUE);
+                whCur->lpNext          = NULL;
+				whCur->dwBytesRecorded = 0;
+				whCur->dwFlags        &= ~WHDR_DONE;
+				LeaveCriticalSection(&CriticalSection );
+				mmr = waveInAddBuffer(shWaveIn, whCur, sizeof(WAVEHDR));
+				EnterCriticalSection(&CriticalSection );
+				assert(mmr == MMSYSERR_NOERROR);
+				/* PO-XXX: Commenting out as it appears to be too keen a
+				 * check in some instances - Also seems to be more relevant
+				 * to playback. e.g. Also some drivers aren't perfect.
+				assert(whCur->dwFlags & WHDR_INQUEUE);*/
+				dwBytesUsedAtReadHead = 0;
+            } 
+
+			assert((int)dwBytesUsedAtReadHead < blksz);
         }
+		LeaveCriticalSection(&CriticalSection);
 
         assert(done <= buf_bytes);
-	UNUSED(ad);
+		UNUSED(ad);
         return done;
 }
 
@@ -1210,22 +1226,22 @@
 void
 w32sdk_audio_wait_for(audio_desc_t ad, int delay_ms)
 {
-        if (whReadList == NULL) {
-                DWORD dwRes;
-		dwRes = WaitForSingleObject(hAudioReady, delay_ms);
-		switch(dwRes) {
-		case WAIT_TIMEOUT:
-			debug_msg("No audio (%d ms wait timeout)\n", delay_ms);
-			dumpReadHdrStats();
-			break;
-		case WAIT_FAILED:
-			debug_msg("Wait failed (error %u)\n", GetLastError());
-			break;
-		}
-                ResetEvent(hAudioReady);
-        }
+     if (whReadList == NULL) {
+            DWORD dwRes;
+			dwRes = WaitForSingleObject(hAudioReady, delay_ms);
+			switch(dwRes) {
+				case WAIT_TIMEOUT:
+					debug_msg("No audio (%d ms wait timeout)\n", delay_ms);
+					dumpReadHdrStats();
+					break;
+				case WAIT_FAILED:
+					debug_msg("Wait failed (error %u)\n", GetLastError());
+					break;
+			}
+            ResetEvent(hAudioReady);
+    }
 	waveInStart(shWaveIn);
-        UNUSED(ad);
+    UNUSED(ad);
 }
 
 static int audio_dev_open = 0;
@@ -1486,6 +1502,7 @@
                         for(j = 0; j < n_loop_ports && nLoopGain != 0; j++) {
                                 if (strcmp(loop_ports[j].name, input_ports[i].name) == 0) {
                                         mixerEnableOutputLine((HMIXEROBJ)hMixer, loop_ports[j].port, 1);
+
                                         /* mixerSetLineGain((HMIXEROBJ)hMixer, loop_ports[j].port, nLoopGain); */
                                 }
                         }



More information about the Sumover-dev mailing list