[xiph-cvs] cvs commit: ao/src/plugins/mmsound mmsound.c

Chris Wolf cwolf at xiph.org
Sat Sep 8 14:10:35 PDT 2001



cwolf       01/09/08 14:10:35

  Modified:    src/plugins/mmsound mmsound.c
  Log:
  Fix semaphore logic. Add critical sectioning to insure atomic state updates.
  Made buffer mechanism more generic -- it's now a circular block buffer.

Revision  Changes    Path
1.3       +82 -31    ao/src/plugins/mmsound/mmsound.c

Index: mmsound.c
===================================================================
RCS file: /usr/local/cvsroot/ao/src/plugins/mmsound/mmsound.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- mmsound.c	2001/09/08 00:04:28	1.2
+++ mmsound.c	2001/09/08 21:10:35	1.3
@@ -29,13 +29,21 @@
 #include <ao/ao.h>
 #include <ao/plugin.h>
 
-typedef struct ao_mmsound_internal {
-	HWAVEOUT m_hWaveOut;
-	WAVEHDR	m_waveHeader[2];
-	uint_32 buf_size;
-	void *buffer[2];
-	int currentb;
-  HANDLE notdone;
+
+#define MAXBUF 5            // Max buffers in circular buffer queue
+#define DEFAULTBUFTIME 3    // default to three seconds total buffer time
+
+typedef struct ao_mmsound_internal 
+{
+	HWAVEOUT          m_hWaveOut;
+	WAVEHDR	          m_waveHeader[MAXBUF];
+	uint_32           buf_size;
+	void             *buffer[MAXBUF];
+  int               next_in;
+  int               next_out;
+  int               timeout_msec;
+  HANDLE            hSema;  // semaphore for foreground/background coordination
+  CRITICAL_SECTION  lock;   // concurrency control for atomic state updates
 } ao_mmsound_internal;
 
 static char *ao_mmsound_options[] = {"buf_size"};
@@ -57,9 +65,21 @@
 {
   ao_mmsound_internal *internal = (ao_mmsound_internal *)dwInstance;
 
+//  printf("*********  %x   Next in: %d  Next out: %d\n", 
+//    uMsg, internal->next_in, internal->next_out);
+
         if (uMsg == WOM_DONE)
         {
-		ReleaseSemaphore(internal->notdone, 1, NULL);
+    EnterCriticalSection(&internal->lock);
+    internal->next_out++;
+
+    if (internal->next_out == internal->next_in)
+    {
+      internal->next_in = internal->next_out = 0;
+		  ReleaseSemaphore(internal->hSema, 1, NULL);
+    }
+
+    LeaveCriticalSection(&internal->lock);
         }
 }
 
@@ -103,6 +123,7 @@
  */
 int ao_plugin_open(ao_device *device, ao_sample_format *format)
 {
+  int i;
         ao_mmsound_internal *internal = (ao_mmsound_internal *) device->internal;
         
         MMRESULT errCode;
@@ -127,16 +148,21 @@
 
         if(internal->buf_size == 0)
         {
-		internal->buf_size = 352800;
+		internal->buf_size = wfx.nAvgBytesPerSec * DEFAULTBUFTIME;
         }
+
+  internal->timeout_msec = (internal->buf_size / wfx.nAvgBytesPerSec) * 1000;
+
+  for (i=0; i<MAXBUF; i++)
+  {
+	  internal->buffer[i] = malloc(internal->buf_size);
+    memset(&internal->m_waveHeader[i],0,sizeof(WAVEHDR));
+  }
 
-	memset(&internal->m_waveHeader[0],0,sizeof(WAVEHDR));
-	memset(&internal->m_waveHeader[1],0,sizeof(WAVEHDR));
-	internal->buffer[0] = malloc(internal->buf_size);
-	internal->buffer[1] = malloc(internal->buf_size);
-	internal->currentb = 0;
+  internal->next_in = internal->next_out = 0;
 
-	internal->notdone = CreateSemaphore(NULL, 0, 1, NULL);
+	internal->hSema = CreateSemaphore(NULL, MAXBUF-1, MAXBUF, NULL);
+  InitializeCriticalSection(&internal->lock);
 
         device->driver_byte_format = AO_FMT_NATIVE;
         
@@ -150,37 +176,62 @@
                 uint_32 num_bytes)
 {
         ao_mmsound_internal *internal = (ao_mmsound_internal *) device->internal;
+
+  EnterCriticalSection(&internal->lock);
         
         if(num_bytes > internal->buf_size)
+  {
+    LeaveCriticalSection(&internal->lock);
                 return 0;
+  }
 
-	if (internal->m_waveHeader[internal->currentb].dwFlags&WHDR_PREPARED)
-		waveOutUnprepareHeader(internal->m_hWaveOut,&internal->m_waveHeader[internal->currentb],sizeof(WAVEHDR));
-	
-	// Prepare internal->buffer[n] to be inteserted int WaveOut buffer.
-	memcpy(internal->buffer[internal->currentb], output_samples, num_bytes);
+//  printf("*** Next in: %d   Next out: %d\n", 
+//    internal->next_in, internal->next_out);
+	if (internal->m_waveHeader[internal->next_in].dwFlags&WHDR_PREPARED)
+		waveOutUnprepareHeader(internal->m_hWaveOut,
+                          &internal->m_waveHeader[internal->next_in],
+                           sizeof(WAVEHDR));
+	
+	// Prepare internal->buffer[n] to be inserted into WaveOut buffer.
+	memcpy(internal->buffer[internal->next_in], output_samples, num_bytes);
+
+	internal->m_waveHeader[internal->next_in].lpData = 
+    (char*)internal->buffer[internal->next_in];
+
+	internal->m_waveHeader[internal->next_in].dwBufferLength = 
+    (unsigned long)num_bytes;
 
-	internal->m_waveHeader[internal->currentb].lpData = (char*)internal->buffer[internal->currentb];
-	internal->m_waveHeader[internal->currentb].dwBufferLength = (unsigned long)num_bytes;
-	waveOutPrepareHeader(internal->m_hWaveOut,&internal->m_waveHeader[internal->currentb],sizeof(WAVEHDR));
+	waveOutPrepareHeader(internal->m_hWaveOut,
+                      &internal->m_waveHeader[internal->next_in], sizeof(WAVEHDR));
 
         // Send internal->buffer[n] to the WaveOut device buffer.
-	waveOutWrite(internal->m_hWaveOut,&internal->m_waveHeader[internal->currentb],sizeof(WAVEHDR));
-	WaitForSingleObject(internal->notdone, INFINITE);
+	waveOutWrite(internal->m_hWaveOut,
+              &internal->m_waveHeader[internal->next_in], sizeof(WAVEHDR));
 
-	internal->currentb++;
-	if(internal->currentb >= 2) internal->currentb = 0;
+  internal->next_in++;
+  LeaveCriticalSection(&internal->lock);
+  WaitForSingleObject(internal->hSema, internal->timeout_msec);
 
         return 1;
 }
 
 int ao_plugin_close(ao_device *device)
 {
+  int i;
         ao_mmsound_internal *internal = (ao_mmsound_internal *) device->internal;
 
-	CloseHandle(internal->notdone);
-	free(internal->buffer[0]);
-	free(internal->buffer[1]);
+
+  // Wait for last block to finish playing
+  while ( internal->next_in !=  internal->next_out )
+  {
+    WaitForSingleObject(internal->hSema, internal->timeout_msec);
+  }
+
+	CloseHandle(internal->hSema);
+  DeleteCriticalSection(&internal->lock);
+
+  for (i=0; i<MAXBUF; i++)
+	  free(internal->buffer[i]);
         
         waveOutReset(internal->m_hWaveOut);
         waveOutClose(internal->m_hWaveOut);
@@ -193,4 +244,4 @@
         ao_mmsound_internal *internal = (ao_mmsound_internal *) device->internal;
 
         free(internal);
-}
\ No newline at end of file
+}

--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list