[xiph-cvs] cvs commit: vorbis-tools/ogg123 ao_interface.c ao_interface.h buffer.c buffer.h curl_interface.c ogg123.c

Stan Seibert volsung at xiph.org
Sat Oct 13 22:42:54 PDT 2001



volsung     01/10/13 22:42:53

  Modified:    ogg123   Tag: volsung_kc_20011011 ao_interface.c
                        ao_interface.h buffer.c buffer.h curl_interface.c
                        ogg123.c
  Log:
  Buffer rewrite I'm playing with.  The code is much simplified by assuming
  that the decoder thread can never shrink the amount of data in the buffer.
  
  This still has two major problems:
  - I haven't worked through all the signal handling issues.
  - I'm stomping data when I fill up the circular buffer.
  
  This commit is to make sure I don't accidentally destroy my work.  You can
  look, but don't touch because I'm only partially done.

Revision  Changes    Path
No                   revision

No                   revision

1.5.2.7.2.1 +6 -8      vorbis-tools/ogg123/ao_interface.c

Index: ao_interface.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ao_interface.c,v
retrieving revision 1.5.2.7
retrieving revision 1.5.2.7.2.1
diff -u -r1.5.2.7 -r1.5.2.7.2.1
--- ao_interface.c	2001/08/31 18:01:12	1.5.2.7
+++ ao_interface.c	2001/10/14 05:42:51	1.5.2.7.2.1
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: ao_interface.c,v 1.5.2.7 2001/08/31 18:01:12 kcarnold Exp $
+ last mod: $Id: ao_interface.c,v 1.5.2.7.2.1 2001/10/14 05:42:51 volsung Exp $
 
  ********************************************************************/
 
@@ -45,21 +45,19 @@
     return devices_list;
 }
 
-size_t devices_write(void *ptr, size_t size, size_t nmemb, devices_t * d)
+int devices_write(void *ptr, size_t size, size_t nmemb, devices_t * d)
 {
-  size_t i, total = 0;
+  size_t i;
   devices_t * start = d;
   for (i=0; i < nmemb; i++) {
     d = start;
     while (d != NULL) {
-      int ret = ao_play(d->device, ptr, size);
-      if (ret < size)
-	return total + ret;
-      total += ret;
+      if (ao_play(d->device, ptr, size) == 0)
+	return 0; /* error occurred */
       d = d->next_device;
     }
   }
-  return total;
+  return 1;
 }
 
 int add_option(ao_option ** op_h, const char *optstring)

1.1.2.3.2.1 +2 -2      vorbis-tools/ogg123/Attic/ao_interface.h

Index: ao_interface.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/Attic/ao_interface.h,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.3.2.1
diff -u -r1.1.2.3 -r1.1.2.3.2.1
--- ao_interface.h	2001/08/12 18:34:46	1.1.2.3
+++ ao_interface.h	2001/10/14 05:42:51	1.1.2.3.2.1
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
  
- last mod: $Id: ao_interface.h,v 1.1.2.3 2001/08/12 18:34:46 kcarnold Exp $
+ last mod: $Id: ao_interface.h,v 1.1.2.3.2.1 2001/10/14 05:42:51 volsung Exp $
  
 ********************************************************************/
 
@@ -33,7 +33,7 @@
 
 devices_t *append_device(devices_t * devices_list, int driver_id,
                          ao_option * options, char *filename);
-size_t devices_write(void *ptr, size_t size, size_t nmemb, devices_t * d);
+int devices_write(void *ptr, size_t size, size_t nmemb, devices_t * d);
 int add_option(ao_option ** op_h, const char *optstring);
 void ao_onexit (int exitcode, void *devices);
 void close_audio_devices (devices_t *devices);

1.7.2.23.2.1 +232 -383  vorbis-tools/ogg123/buffer.c

Index: buffer.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/buffer.c,v
retrieving revision 1.7.2.23
retrieving revision 1.7.2.23.2.1
diff -u -r1.7.2.23 -r1.7.2.23.2.1
--- buffer.c	2001/08/31 18:19:57	1.7.2.23
+++ buffer.c	2001/10/14 05:42:51	1.7.2.23.2.1
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: buffer.c,v 1.7.2.23 2001/08/31 18:19:57 kcarnold Exp $
+ last mod: $Id: buffer.c,v 1.7.2.23.2.1 2001/10/14 05:42:51 volsung Exp $
 
  ********************************************************************/
 
@@ -36,255 +36,203 @@
 #include "ogg123.h"
 #include "buffer.h"
 
-#undef DEBUG_BUFFER
-#undef DEADLOCK_PROTECTION
+#define MIN(x,y)     ( (x) < (y) ? (x) : (y) )
+#define MIN3(x,y,z)  MIN(x,MIN(y,z))
 
+#define DEBUG_BUFFER
+
 #ifdef DEBUG_BUFFER
 FILE *debugfile;
-#define DEBUG0(x) do { if (pthread_self() != buf->BufferThread) fprintf (debugfile, "R: " x "\n" ); else fprintf (debugfile, "W: " x "\n" ); } while (0)
-#define DEBUG1(x, y) do { if (pthread_self() != buf->BufferThread) fprintf (debugfile, "R-: " x "\n", y ); else fprintf (debugfile, "W-: " x "\n", y ); } while (0)
-#define DUMP_BUFFER_INFO(buf) do { fprintf (debugfile, "Buffer info: -reader=%p  -writer=%p  -buf=%p  -end=%p -curfill=%ld\n", buf->reader, buf->writer, buf->buffer, buf->end, buf->curfill); } while (0)
+#define DEBUG(x, y...) { if (pthread_self() != buf->thread) fprintf (debugfile, "D: " x "\n", ## y ); else fprintf (debugfile, "P: " x "\n", ## y ); }
 #else
-#define DEBUG0(x)
-#define DEBUG1(x, y)
-#define DUMP_BUFFER_INFO(buf)
+#define DEBUG(x, y...)
 #endif
-
-#define LOCK_MUTEX(mutex) do { DEBUG1("Locking mutex %s.", #mutex); pthread_mutex_lock (&(mutex)); } while (0)
-#define UNLOCK_MUTEX(mutex) do { DEBUG1("Unlocking mutex %s", #mutex); pthread_mutex_unlock(&(mutex)); } while (0) 
 
-#ifdef DEADLOCK_PROTECTION
-#define TIMEDWAIT(cond, mutex, sec, nsec) do { struct timeval now; struct timespec timeout; gettimeofday(&now, NULL); timeout.tv_sec = now.tv_sec + sec; timeout.tv_nsec = now.tv_usec * 1000 + nsec; pthread_cond_timedwait (&(cond), &(mutex), &timeout); } while (0)
-#else
-#define TIMEDWAIT(cond, mutex, sec, nsec) do { pthread_cond_wait (&(cond), &(mutex)); } while (0)
-#endif
+#define LOCK_MUTEX(mutex) { DEBUG("Locking mutex %s.", #mutex); pthread_mutex_lock (&(mutex)); }
+#define UNLOCK_MUTEX(mutex) { DEBUG("Unlocking mutex %s", #mutex); pthread_mutex_unlock(&(mutex)); }
+#define COND_WAIT(cond, mutex) { DEBUG("Unlocking %s and waiting on %s", #mutex, #cond); pthread_cond_wait(&(cond), &(mutex)); }
+#define COND_SIGNAL(cond) { DEBUG("Signalling %s", #cond); pthread_cond_signal(&(cond)); }
 
-void Prebuffer (buf_t * buf)
+void _buffer_thread_cleanup (void *arg)
 {
-  if (buf->prebuffer > 0)
-    {
-      LOCK_MUTEX (buf->StatMutex);
-      buf->StatMask |= STAT_PREBUFFERING;
-      UNLOCK_MUTEX (buf->StatMutex);
-    }
-}
+  buf_t *buf = (buf_t *)arg;
 
-void UnPrebuffer (buf_t * buf)
-{
-  LOCK_MUTEX (buf->StatMutex);
-  buf->StatMask &= ~STAT_PREBUFFERING;
-  UNLOCK_MUTEX (buf->StatMutex);
-  pthread_cond_signal (&buf->DataReadyCondition);
-}
+  DEBUG("Enter _buffer_thread_cleanup");
 
-void SignalAll (buf_t *buf)
-{
-  /* inexcusable laziness on the part of the programmer. */
-  pthread_cond_broadcast (&buf->DataReadyCondition);
-  pthread_cond_broadcast (&buf->UnderflowCondition);
-  pthread_cond_broadcast (&buf->OverflowCondition);
+  /* Cleanup thread data structures */
+  pthread_mutex_destroy (&buf->mutex);
+  pthread_cond_destroy (&buf->playback_cond);
+  pthread_cond_destroy (&buf->write_cond);
 }
 
-void PthreadCleanup (void *arg)
-{
-#ifdef DEBUG_BUFFER
-  buf_t *buf = (buf_t*) arg;
-#endif
-  
-  DEBUG0("PthreadCleanup");
-#if 0
-  UNLOCK_MUTEX (buf->SizeMutex);
-  UNLOCK_MUTEX (buf->StatMutex);
-
-  /* kludge to get around pthreads vs. signal handling */
-  pthread_cond_broadcast (&buf->DataReadyCondition);
-  pthread_cond_broadcast (&buf->UnderflowCondition);
-  pthread_cond_broadcast (&buf->OverflowCondition);
-  UNLOCK_MUTEX (buf->SizeMutex);
-  UNLOCK_MUTEX (buf->StatMutex);
-#endif
-}
-
-void BufferAsserts(buf_t *buf)
-{
-  DUMP_BUFFER_INFO(buf);
-  assert (buf->curfill >= 0);
-  assert (buf->writer >= buf->buffer);
-  assert (buf->writer <= buf->end);
-  assert (buf->reader >= buf->buffer);
-  assert (buf->reader <= buf->end);
-}
 
-void* BufferFunc (void *arg)
+void _buffer_thread_init (buf_t *buf)
 {
   sigset_t set;
-  buf_t *buf = (buf_t*) arg;
-  volatile buf_t *vbuf = (volatile buf_t*) buf; /* optimizers... grr */
-  size_t WriteThisTime = 0;
-  chunk *NewWriterPtr;
-  char EOSApplies = 0, tmpEOS;
 
-  DEBUG0("BufferFunc");
-  sigfillset (&set);
-  pthread_sigmask (SIG_SETMASK, &set, NULL);
+  DEBUG("Enter _buffer_thread_init");
 
+  /* Block signals to this thread */
+  sigfillset (&set);
+  //pthread_sigmask (SIG_SETMASK, &set, NULL);
+  
   /* Run the initialization function, if there is one */
-  if (buf->init_func)
+  if (buf->init_func) 
     {
       int ret = buf->init_func (buf->initData);
       if (!ret)
         pthread_exit ((void*)ret);
     }
+	
+  /* Setup pthread variables */
+  pthread_mutex_init (&buf->mutex, NULL);
+  pthread_cond_init (&buf->write_cond, NULL);
+  pthread_cond_init (&buf->playback_cond, NULL);
+
+  /* Initialize buffer flags */
+  buf->prebuffering = buf->prebuffer_size > 0;
+  buf->paused = 0;
+  buf->eos = 0;
+  
+  buf->curfill = 0;
+  buf->start = 0;
+}
 
-  pthread_cleanup_push (PthreadCleanup, buf);
 
-  while (1)
-    {
-      LOCK_MUTEX (buf->SizeMutex);
-    checkPlaying:
-      while (!(buf->Playing) || 
-	     (buf->StatMask & STAT_PREBUFFERING)) {
-	DEBUG1 ("waiting on !playing || prebuffering (stat=%d)", buf->StatMask);
-	pthread_cond_signal (&buf->UnderflowCondition);
-	TIMEDWAIT (buf->DataReadyCondition, buf->SizeMutex, 1, 0);
-      }
+void *_buffer_thread_func (void *arg)
+{
+  buf_t *buf = (buf_t*) arg;
+  size_t write_amount;
+  
+  DEBUG("Enter _buffer_thread_func");
+  
+  _buffer_thread_init(buf);
 
-      BufferAsserts(buf);
+  pthread_cleanup_push (_buffer_thread_cleanup, buf);
+  
+  DEBUG("Start main play loop");
+  
+  while (1) 
+    {
 
-      if (buf->FlushPending)
+      DEBUG("Check for something to play");
+      /* Block until we can play something */
+      LOCK_MUTEX (buf->mutex);
+      if (buf->prebuffering || 
+	  buf->paused || 
+	  (buf->curfill < buf->audio_chunk_size && !buf->eos))
         {
-	flushing:
-	  DEBUG0("executing pending flush");
-	  UNLOCK_MUTEX (buf->SizeMutex);
-	  UnPrebuffer (buf);
-	  LOCK_MUTEX (buf->SizeMutex);
-	  DEBUG0("setting curfill to 0");
-	  buf->curfill = 0;
-	  buf->writer = buf->reader;
-	  UNLOCK_MUTEX (buf->SizeMutex);
-	  Prebuffer (buf);
-	  SignalAll(buf);
-	  buf->FlushPending = 0;
-	  if (buf->eos)
-	    buf->write_func (buf->writer, 0, 0, buf->data, buf->eos);
-	  buf->eos = 0;
-	  LOCK_MUTEX (buf->SizeMutex);
+	  DEBUG("Waiting for more data to play.");
+	  COND_WAIT(buf->playback_cond, buf->mutex);
         }
 
-      if (buf->curfill == 0) {
-	DEBUG0 ("signalling buffer underflow");
-	pthread_cond_signal (&buf->UnderflowCondition);
-	Prebuffer (buf);
-	if (buf->FlushPending)
-	  goto flushing;
-	if (!buf->ReaderActive) {
-	  /* if we never reported EOS to the output, now or never... */
-	  UNLOCK_MUTEX (buf->SizeMutex);
-	  buf->write_func (buf->writer, 0, 0, buf->data, 1);
-	  pthread_exit (NULL);
-	}
-	DEBUG0 ("waiting on data ready");
-	TIMEDWAIT (buf->DataReadyCondition, buf->SizeMutex, 1, 0);
-	goto checkPlaying;
-      }
+      DEBUG("Ready to play");
+
+      /* Figure out how much we can play in the buffer */
+
+      /* For simplicity, the number of bytes played must satisfy the following
+         three requirements:
+	 1. Do not play more bytes than are stored in the buffer.
+	 2. Do not play more bytes than the suggested audio chunk size.
+	 3. Do not run off the end of the buffer. */
+      write_amount = MIN3(buf->curfill, buf->audio_chunk_size, 
+			  buf->size - buf->start);
+      UNLOCK_MUTEX(buf->mutex);
+      
+      /* No need to lock mutex here because the other thread will
+         NEVER reduce the number of bytes stored in the buffer */
+      DEBUG("Sending %d bytes to the audio device", write_amount);
+      buf->write_func(buf->buffer + buf->start, sizeof(chunk), write_amount,
+		      buf->data, buf->eos);
+      
+      LOCK_MUTEX(buf->mutex);
+      buf->curfill -= write_amount;
+      buf->start = (buf->start + write_amount) % buf->size;
+      DEBUG("Updated buffer fill, curfill = %ld", buf->curfill);
+
+      /* If we've essentially emptied the buffer and prebuffering is enabled,
+	 we need to do another prebuffering session */
+      if (!buf->eos && (buf->curfill < buf->audio_chunk_size))
+	buf->prebuffering = buf->prebuffer_size > 0;
+
+      /* Signal a waiting decoder thread that they can put more audio into the
+	 buffer */
+      DEBUG("Signal decoder thread that buffer space is available");
+      COND_SIGNAL(buf->write_cond);
+      UNLOCK_MUTEX(buf->mutex);
+    }
+
+  /* should never get here */
+  pthread_cleanup_pop(1);
+  DEBUG("exiting buffer_thread_func");
+}
+
+
+void _submit_data_chunk (buf_t *buf, chunk *data, size_t size)
+{
+  long   buf_write_pos; /* offset of first available write location */
+  size_t write_size;
+
+  DEBUG("Enter _submit_data_chunk, size %d", size);
 
-      EOSApplies = 0;
+  /* Put the data into the buffer as space is made available */
+  while (size > 0)
+    {
 
-      if (buf->reader < buf->writer)
+      /* Section 1: Write a chunk of data */
+      DEBUG("Obtaining lock on buffer");
+      LOCK_MUTEX(buf->mutex);
+      if (buf->size - buf->curfill > 0)
         {
-	  /* we have all the way to buf->end: 
-	   * |-------------------------------|
-	   * |-^       ^---------------------|
-	   *  reader   writer, our range
-	   * EOS applicable only if reader is at beginning of buffer
-	   */
-	  DEBUG1("up to buf->end, buf->end - buf->writer + 1 = %d", buf->end - buf->writer + 1);
-	  if (buf->end - buf->writer + 1 > buf->OptimalWriteSize) {
-	    WriteThisTime = buf->OptimalWriteSize;
-	    NewWriterPtr = buf->writer + WriteThisTime;
-	  } else {
-	    NewWriterPtr = buf->buffer;
-	    WriteThisTime = buf->end - buf->writer + 1;
-	    if (buf->reader == buf->buffer)
-	      EOSApplies = 1;
-	  }
+	  /* Figure how much we can write into the buffer.  Requirements:
+	     1. Don't write more data than we have.
+	     2. Don't write more data than we have room for.
+	     3. Don't write past the end of the buffer. */
+	  buf_write_pos = (buf->start + buf->curfill) % buf->size;
+	  write_size = MIN3(size, buf->size - buf->curfill, 
+			    buf->size - buf_write_pos);
+
+	  memmove (buf->buffer + buf_write_pos, data, write_size);
+	  buf->curfill += write_size;
+	  size -= write_size;
+	  DEBUG("writing chunk into buffer, curfill = %ld", buf->curfill);
         }
       else
         {
-	  /* we have up to buf->reader:
-	   * |-------------------------------|
-	   *    ^--------------^
-	   *   writer         reader
-	   * but we can't use buf->reader itself, becuase that's not in the data.
-	   * EOS applicable if we're reading right up to reader.
-	   */
-	  DEBUG1("up to buf->reader, buf->reader - buf->writer = %d", buf->reader - buf->writer);
-	  if (buf->reader - buf->writer > buf->OptimalWriteSize)
-	    WriteThisTime = buf->OptimalWriteSize;
-	  else {
-	    WriteThisTime = buf->reader - buf->writer;
-	    EOSApplies = 1;
-	  }
-	  NewWriterPtr = buf->writer + WriteThisTime;
+	  /* No room for more data, wait until there is */
+	  DEBUG("No room for data in buffer.  Waiting.");
+	  COND_WAIT(buf->write_cond, buf->mutex);
         }
       
-      tmpEOS = EOSApplies && buf->eos ;
-
-      DEBUG0("writing chunk to output");
-      /* unlock while playing sample */
-      buf->bufferWriting = 1;
-      UNLOCK_MUTEX (buf->SizeMutex);
-      DEBUG1("WriteThisTime=%d", WriteThisTime);
-      buf->write_func (buf->writer, WriteThisTime, 1, buf->data, tmpEOS);
-
-      LOCK_MUTEX (buf->SizeMutex);
-      buf->bufferWriting = 0;
-      if (vbuf->curfill == 0)
+      /* Section 2: signal if we are not prebuffering, done
+         prebuffering, or paused */
+      if (buf->prebuffering && (buf->prebuffer_size <= buf->curfill))
         {
-	  /* buffer was flushed while we were writing (and had the mutex unlocked)
-	   * signal buffer underflow and data ready to appease anyone waiting.
-	   * don't move the writer pointer because the reader has been set to its
-	   * old value. */
-	  UNLOCK_MUTEX (buf->SizeMutex);
-	  pthread_cond_broadcast (&buf->DataReadyCondition);
-	  pthread_cond_broadcast (&buf->UnderflowCondition);
-	  LOCK_MUTEX (buf->SizeMutex);
+	  DEBUG("prebuffering done")
+	    buf->prebuffering = 0; /* done prebuffering */
         }
-      else
+
+      if (!buf->prebuffering && !buf->paused)
         {
-	  buf->writer = NewWriterPtr;
-	  vbuf->curfill -= WriteThisTime;
+	  DEBUG("Signalling playback thread that more data is available.");
+	  COND_SIGNAL(buf->playback_cond);      
         }
+      else
+	DEBUG("Not signalling playback thread since prebuffering or paused.");
+      UNLOCK_MUTEX(buf->mutex);
+    }
 
-      if (EOSApplies) {
-	if (tmpEOS != buf->eos) {
-	  /* EOS was signalled or cleared while we were playing, so that sample
-	   * didn't get EOS set. Call write_func with no data, just
-	   * the right EOS flag. write_func is called here with the
-	   * locked; it better not take too long if size == nmemb == 0. */
-	  tmpEOS = buf->eos;
-	  buf->write_func (buf->writer, 0, 0, buf->data, tmpEOS);
-	}
-      }
+  DEBUG("Exit submit_data_chunk");
+}
 
-      if (tmpEOS)
-	buf->eos = 0;
 
-      UNLOCK_MUTEX (buf->SizeMutex);
+/* ------------------ Begin public interface ------------------ */
 
-      /* slight abuse of the DataReady condition, but makes sense. */
-      DEBUG0 ("signalling buffer no longer full");
-      if (buf->curfill + WriteThisTime + buf->OptimalWriteSize >= buf->size || tmpEOS)
-	pthread_cond_signal (&buf->DataReadyCondition);
-   }
-  /* should never get here */
-  pthread_cleanup_pop(1);
-  DEBUG0("exiting");
-}
+/* --- Buffer allocation --- */
 
-buf_t *StartBuffer (long size, long prebuffer, void *data, 
-		    pWriteFunc write_func, void *initData, 
-		    pInitFunc init_func, int OptimalWriteSize)
+buf_t *buffer_create (long size, long prebuffer_size, void *data, 
+		      pWriteFunc write_func, void *initData, 
+		      pInitFunc init_func, int audio_chunk_size)
 {
   buf_t *buf = malloc (sizeof(buf_t) + sizeof (chunk) * (size - 1));
 
@@ -294,15 +242,14 @@
       exit (1);
     }
 
-  /* we no longer need those hacked-up shared memory things! yippee! */
-
 #ifdef DEBUG_BUFFER
   debugfile = fopen ("/tmp/bufferdebug", "w");
   setvbuf (debugfile, NULL, _IONBF, 0);
 #endif
 
   /* Initialize the buffer structure. */
-  DEBUG0("buffer init");
+  DEBUG("buffer_create, size = %ld", size);
+
   memset (buf, 0, sizeof(*buf));
 
   buf->data = data;
@@ -310,216 +257,118 @@
 
   buf->initData = initData;
   buf->init_func = init_func;
+  
+  /* Correct for impossible chunk sizes */
+  if (audio_chunk_size > size || audio_chunk_size == 0)
+    audio_chunk_size = size / 2;
 
-  buf->reader = buf->writer = buf->buffer;
-  buf->end = buf->buffer + size;
-  if (OptimalWriteSize > size || OptimalWriteSize == 0)
-    OptimalWriteSize = size / 2;
-  buf->OptimalWriteSize = OptimalWriteSize;
+  buf->audio_chunk_size = audio_chunk_size;
+  buf->prebuffer_size = prebuffer_size;
   buf->size = size;
-  buf->prebuffer = prebuffer;
-  Prebuffer (buf);
-  buf->Playing = 1;
-  buf->ReaderActive = buf->WriterActive = 1;
-
-  /* pthreads initialization */
-  pthread_mutex_init (&buf->SizeMutex, NULL);
-  pthread_cond_init (&buf->UnderflowCondition, NULL);
-  pthread_cond_init (&buf->OverflowCondition, NULL);
-  
-  pthread_create(&buf->BufferThread, NULL, BufferFunc, buf);
 
   return buf;
 }
+
 
-void _SubmitDataChunk (buf_t *buf, chunk *data, size_t size)
+void buffer_destroy (buf_t *buf)
 {
-  char PrevSize;
-  DEBUG1("submit_chunk, size %d", size);
-  LOCK_MUTEX (buf->SizeMutex);
-
-  PrevSize = buf->curfill;
-  BufferAsserts(buf);
-
-  /* wait on buffer overflow or ack for eos */
-  while (buf->curfill + size > buf->size || buf->eos) {
-    /* for really small buffers */
-    pthread_cond_signal (&buf->DataReadyCondition);
-    UnPrebuffer (buf);
-    TIMEDWAIT (buf->DataReadyCondition, buf->SizeMutex, 1, 0);
-  }
-
-  DEBUG0("writing chunk into buffer");
-  buf->curfill += size;
-  /* we're guaranteed to have enough space in the buffer by now */
-  if (buf->reader < buf->writer && buf->reader + size <= buf->end) {
-    DEBUG0("writer before end");
-    /* don't worry about falling off end */
-    memmove (buf->reader, data, size);
-    buf->reader += size;
-  } else {
-    size_t avail = buf->end - buf->reader + 1;
-    DEBUG0("don't run over the end!");
-    if (avail > size)
-      memmove (buf->reader, data, size);
-    else {
-      memmove (buf->reader, data, avail);
-      size -= avail;
-      data += avail;
-      buf->reader = buf->buffer;
-      DEBUG1("unconditional write of %d", size);
-      memmove (buf->reader, data, size);
-    }
-    buf->reader += size;
-  }
+  DEBUG("buffer_destroy");
+  free(buf);
+}
+
 
-  BufferAsserts(buf);
-    
-  UNLOCK_MUTEX (buf->SizeMutex);
+/* --- Buffer thread control --- */
 
-  if ((buf->StatMask & STAT_PREBUFFERING)
-      && buf->curfill + 1 >= buf->prebuffer) {
-    DEBUG0("prebuffering done, starting writer");
-    UnPrebuffer (buf);
-  }
-  else if (PrevSize == 0)
-    pthread_cond_signal (&buf->DataReadyCondition);
+int buffer_thread_start   (buf_t *buf)
+{
+  DEBUG("Starting new thread.");
 
-  DEBUG0("submit_chunk exit");
+  return pthread_create(&buf->thread, NULL, _buffer_thread_func, buf);
 }
 
-void SubmitData (buf_t *buf, chunk *data, size_t size, size_t nmemb)
+/* WARNING: DO NOT call buffer_submit_data after you pause the
+   playback thread, or you run the risk of deadlocking.  Call
+   buffer_thread_unpause first. */
+void buffer_thread_pause   (buf_t *buf)
 {
-  size_t i, s;
+  DEBUG("Pausing playback thread");
 
-  size *= nmemb;
-  for (i = 0; i < size; i += buf->OptimalWriteSize) {
-    s = i + buf->OptimalWriteSize <= size ? buf->OptimalWriteSize : size - i;
-    _SubmitDataChunk (buf, data, s);
-    data += s;
-  }
-}
-
-/* this is the only function here that may be called from
- * a signal handler. */
-void buffer_flush (buf_t *buf)
-{
-  DEBUG0("flush buffer");
-  buf->FlushPending = 1;
-  if (!buf->BufferThread || buf->StatMask & STAT_INACTIVE)
-    buf->curfill = 0;
-  DEBUG0("flush buffer done");
-}
-
-void buffer_WaitForEmpty (buf_t *buf)
-{
-  DEBUG0("waiting for empty");
-  DUMP_BUFFER_INFO(buf);
-  UnPrebuffer (buf);
-  DEBUG0("unprebuffered");
-  SignalAll (buf);
-  DEBUG0("signalled all");
-  LOCK_MUTEX(buf->SizeMutex);
-  while (buf->curfill > 0)
-    TIMEDWAIT(buf->UnderflowCondition, buf->SizeMutex, 1, 0);
-  DEBUG0("done waiting");
-  UNLOCK_MUTEX (buf->SizeMutex);
-  DEBUG0("buffer empty");
-  if (!buf->ReaderActive) {
-    pthread_join (buf->BufferThread, NULL);
-    buf->BufferThread = 0;
-    buf->StatMask |= STAT_INACTIVE;
-  }
-  else
-    Prebuffer (buf);
+  LOCK_MUTEX(buf->mutex);
+  buf->paused = 1;
+  UNLOCK_MUTEX(buf->mutex);
 }
 
-long buffer_full (buf_t* buf) {
-  return buf->curfill;
-}
 
-void buffer_Pause (buf_t *buf)
+void buffer_thread_unpause (buf_t *buf)
 {
-  buf->Playing = 0;
+  DEBUG("Unpausing playback thread");
+  
+  LOCK_MUTEX(buf->mutex);
+  buf->paused = 0;
+  COND_SIGNAL(buf->playback_cond);
+  UNLOCK_MUTEX(buf->mutex);
 }
 
-void buffer_WaitForPaused (buf_t *buf)
-{
-  buf->Playing = 0;
-  LOCK_MUTEX (buf->SizeMutex);
-  while (buf->bufferWriting)
-    TIMEDWAIT(buf->UnderflowCondition, buf->SizeMutex, 1, 0);
-  UNLOCK_MUTEX (buf->SizeMutex);
-}
 
-void buffer_Unpause (buf_t *buf)
+void buffer_thread_kill    (buf_t *buf)
 {
-  buf->Playing = 1;
-#if 0
-  /* can't signal here; this can be called from sighandler :( */
-  /* pthread_cond_signal (&buf->DataReadyCondition); */
-#else
-  /* this function cannot be called from a signal handler. */
-  pthread_cond_signal (&buf->DataReadyCondition);
-#endif
-}
+  DEBUG("Attempting to kill playback thread.");
 
-char buffer_Paused (buf_t *buf)
-{
-  return (char) !(buf->Playing);
+  /* End thread */
+  pthread_cancel (buf->thread);
+  pthread_join (buf->thread, NULL);
+
+  _buffer_thread_cleanup(buf);
+
+  DEBUG("Playback thread killed.");
 }
+
 
-/* don't TERM or KILL the buffer with this if possible. */
-void buffer_KillBuffer (buf_t *buf, int signo)
+/* --- Data buffering functions --- */
+void buffer_submit_data (buf_t *buf, chunk *data, size_t size, size_t nmemb)
 {
-  pthread_kill (buf->BufferThread, signo);
+  size *= nmemb;
+  _submit_data_chunk (buf, data, size);
 }
 
-void buffer_MarkEOS (buf_t *buf)
+
+void buffer_mark_eos (buf_t *buf)
 {
-  /* lock the mutex here so the writer can have some knowledge of when
-   * the marker is set */
-  LOCK_MUTEX (buf->SizeMutex);
+  DEBUG("buffer_mark_eos");
+
+  LOCK_MUTEX(buf->mutex);
   buf->eos = 1;
-  UNLOCK_MUTEX (buf->SizeMutex);
-  UnPrebuffer (buf);
-  pthread_cond_signal (&buf->DataReadyCondition);
+  COND_SIGNAL(buf->playback_cond);
+  UNLOCK_MUTEX(buf->mutex);
 }
+
 
-void buffer_NewStream (buf_t *buf)
+/* --- Buffer status functions --- */
+
+void buffer_wait_for_empty (buf_t *buf)
 {
-  buf->eos = 0;
-  Prebuffer (buf);
-  pthread_cond_signal (&buf->DataReadyCondition);
+  int empty = 0;
+
+  DEBUG("Enter buffer_wait_for_empty");
+  
+  LOCK_MUTEX(buf->mutex);
+  while (!empty)
+    {
+      if (buf->curfill > 0)
+	{
+	  DEBUG("Buffer curfill = %ld, going back to sleep.", buf->curfill);
+	  COND_WAIT(buf->write_cond, buf->mutex);
+	}
+      else 
+	empty = 1;
+    }
+  UNLOCK_MUTEX(buf->mutex);
+
+  DEBUG("Exit buffer_wait_for_empty");
 }
 
-/* Inform the writer that the reader is quitting and it won't get any
- * more data, ever. */
-void buffer_ReaderQuit (buf_t *buf)
-{
-  UnPrebuffer (buf);
-  buf->ReaderActive = 0;
-  SignalAll (buf);
-}
-
-void buffer_shutdown (buf_t *buf)
-{
-  DEBUG0("shutdown buffer");
-  if (buf && buf->BufferThread) {
-    buffer_WaitForEmpty (buf);
-    pthread_cancel (buf->BufferThread);
-    pthread_join (buf->BufferThread, NULL);
-    buf->BufferThread = 0;
-    buf->StatMask |= STAT_INACTIVE;
-  }
-  DEBUG0("buffer done.");
-}
-
-void buffer_cleanup (buf_t *buf) {
-  if (buf) {
-    buffer_shutdown (buf);
-    PthreadCleanup (buf);
-    memset (buf, 0, sizeof(buf));
-    free (buf);
-  }
+
+long buffer_full (buf_t *buf)
+{
+  return buf->curfill;
 }

1.2.2.16.2.1 +44 -44    vorbis-tools/ogg123/buffer.h

Index: buffer.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/buffer.h,v
retrieving revision 1.2.2.16
retrieving revision 1.2.2.16.2.1
diff -u -r1.2.2.16 -r1.2.2.16.2.1
--- buffer.h	2001/08/23 01:15:46	1.2.2.16
+++ buffer.h	2001/10/14 05:42:51	1.2.2.16.2.1
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
  
- last mod: $Id: buffer.h,v 1.2.2.16 2001/08/23 01:15:46 kcarnold Exp $
+ last mod: $Id: buffer.h,v 1.2.2.16.2.1 2001/10/14 05:42:51 volsung Exp $
  
 ********************************************************************/
 
@@ -35,53 +35,53 @@
   void * initData;
   pInitFunc init_func;
   
-  /* pthreads variables */
-  pthread_t BufferThread;
-  pthread_mutex_t SizeMutex;
-  pthread_mutex_t StatMutex;
-  pthread_cond_t UnderflowCondition; /* signalled on buffer underflow */
-  pthread_cond_t OverflowCondition;  /* signalled on buffer overflow */
-  pthread_cond_t DataReadyCondition; /* signalled when data is ready and it wasn't before */
+  /* pthread variables */
+  pthread_t thread;
+
+  pthread_mutex_t mutex;
+  
+  pthread_cond_t playback_cond; /* signalled when playback can continue */
+  pthread_cond_t write_cond;    /* signalled when more data can be written 
+				   to the buffer */
   
-  char StatMask;
-  /* And the stats that can't be in statmask: */
-  char FlushPending;
-  char Playing;
-
-  char ReaderActive;
-  char WriterActive;
-  int OptimalWriteSize; /* optimal size to write out in chunks of, if possible. */
-  long size;         /* buffer size, for reference */
-  long curfill;      /* how much the buffer is currently filled */
-  long prebuffer;    /* number of chunks to prebuffer */
-  char eos;        /* set if reader is at end of stream */
-  char bufferWriting; /* set if buffer is busy writing data to output */
-  chunk *reader;   /* Chunk the reader is busy with */
-  chunk *writer;   /* Chunk the writer is busy with */
-  chunk *end;      /* Last chunk in the buffer (for convenience) */
-  chunk buffer[1]; /* The buffer itself. It's more than one chunk. */
+  /* buffer info (constant) */
+  int  audio_chunk_size;  /* write data to audio device in this chunk size, 
+			     if possible */
+  long prebuffer_size;    /* number of bytes to prebuffer */
+  long size;              /* buffer size, for reference */
+
+  /* ----- Everything after this point is protected by mutex ----- */
+
+  /* buffering state variables */
+  int prebuffering;
+  int paused;
+  int eos;
+
+  /* buffer data */
+  long curfill;     /* how much the buffer is currently filled */
+  long start;       /* offset in buffer of start of available data */
+  chunk buffer[1];   /* The buffer itself. It's more than one chunk. */
 } buf_t;
 
-#define STAT_PREBUFFERING 1
-#define STAT_INACTIVE 2
+/* --- Buffer allocation --- */
 
-buf_t *StartBuffer (long size, long prebuffer, void *data, 
-		    pWriteFunc write_func, void *initData, 
-		    pInitFunc init_func, int OptimalWriteSize);
-void SubmitData (buf_t *buf, chunk *data, size_t size, size_t nmemb);
-void buffer_MarkEOS (buf_t *buf);
-void buffer_NewStream (buf_t *buf);
-void buffer_ReaderQuit (buf_t *buf);
-void buffer_shutdown (buf_t *buf);
-void buffer_cleanup (buf_t *buf);
-void buffer_flush (buf_t *buf);
-void buffer_WaitForEmpty (buf_t *buf);
-long buffer_full (buf_t *buf);
+buf_t *buffer_create (long size, long prebuffer, void *data, 
+		      pWriteFunc write_func, void *initData, 
+		      pInitFunc init_func, int audio_chunk_size);
+void buffer_destroy (buf_t *buf);
+
+/* --- Buffer thread control --- */
+int  buffer_thread_start   (buf_t *buf);
+void buffer_thread_pause   (buf_t *buf);
+void buffer_thread_unpause (buf_t *buf);
+void buffer_thread_kill    (buf_t *buf);
+
+/* --- Data buffering functions --- */
+void buffer_submit_data (buf_t *buf, chunk *data, size_t size, size_t nmemb);
+void buffer_mark_eos (buf_t *buf);
 
-void buffer_Pause (buf_t *buf);
-void buffer_WaitForPaused (buf_t *buf);
-void buffer_Unpause (buf_t *buf);
-char buffer_Paused (buf_t *buf);
-void buffer_KillBuffer (buf_t *buf, int signo);
+/* --- Buffer status functions --- */
+void buffer_wait_for_empty (buf_t *buf);
+long buffer_full (buf_t *buf);
 
 #endif /* !defined (__BUFFER_H) */

1.1.2.6.2.1 +10 -12    vorbis-tools/ogg123/Attic/curl_interface.c

Index: curl_interface.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/Attic/curl_interface.c,v
retrieving revision 1.1.2.6
retrieving revision 1.1.2.6.2.1
diff -u -r1.1.2.6 -r1.1.2.6.2.1
--- curl_interface.c	2001/08/31 18:01:12	1.1.2.6
+++ curl_interface.c	2001/10/14 05:42:51	1.1.2.6.2.1
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
  
- last mod: $Id: curl_interface.c,v 1.1.2.6 2001/08/31 18:01:12 kcarnold Exp $
+ last mod: $Id: curl_interface.c,v 1.1.2.6.2.1 2001/10/14 05:42:51 volsung Exp $
  
 ********************************************************************/
 
@@ -22,7 +22,7 @@
 #include <string.h> /* for memmove */
 #include <signal.h>		/* for SIGINT */
 
-#undef DEBUG_CURLINTERFACE
+#define DEBUG_CURLINTERFACE
 
 #ifdef DEBUG_CURLINTERFACE
 #define debug(x, y...) do { fprintf (stderr, x , ## y); } while (0)
@@ -42,7 +42,7 @@
   debug ("CurlWriteFunction, submitting %d bytes.\n", size * nmemb);
   if (exit_requested)
     exit(0);
-  SubmitData (buf, ptr, size, nmemb);
+  buffer_submit_data (buf, ptr, size, nmemb);
   Ogg123UpdateStats();
   return size * nmemb;
 }
@@ -159,8 +159,7 @@
   debug ("CurlGo\n");
   ret = curl_easy_perform ((CURL *) data->CurlHandle);
   debug ("curl done.\n");
-  buffer_MarkEOS (buf);
-  buffer_ReaderQuit (buf);
+  buffer_thread_kill (buf);
   curl_easy_cleanup (data->CurlHandle);
   data->CurlHandle = 0;
   return (void *) ret;
@@ -194,14 +193,13 @@
       exit (1);
     }
 
-  debug (" start buffer\n");
-  buf =
-    StartBuffer (inputOpts.BufferSize, inputOpts.Prebuffer, data,
-		 BufferWriteFunction, NULL, NULL, VORBIS_CHUNKIN_SIZE);
+  debug (" create buffer\n");
+  buf = buffer_create (inputOpts.BufferSize, inputOpts.Prebuffer, data,
+		       BufferWriteFunction, NULL, NULL, VORBIS_CHUNKIN_SIZE);
 
   if (!buf)
     {
-      perror ("StartBuffer");
+      perror ("Create Buffer");
       exit (1);
     }
 
@@ -326,6 +324,6 @@
 { 
   StreamBufferClose (buf->data);
   buf->data = 0;
-  buffer_flush (buf);
-  buffer_cleanup (buf);
+  buffer_thread_kill (buf);
+  buffer_destroy (buf);
 }

1.39.2.30.2.1 +34 -75    vorbis-tools/ogg123/ogg123.c

Index: ogg123.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.c,v
retrieving revision 1.39.2.30
retrieving revision 1.39.2.30.2.1
diff -u -r1.39.2.30 -r1.39.2.30.2.1
--- ogg123.c	2001/09/24 21:11:34	1.39.2.30
+++ ogg123.c	2001/10/14 05:42:51	1.39.2.30.2.1
@@ -14,7 +14,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: ogg123.c,v 1.39.2.30 2001/09/24 21:11:34 volsung Exp $
+ last mod: $Id: ogg123.c,v 1.39.2.30.2.1 2001/10/14 05:42:51 volsung Exp $
 
  ********************************************************************/
 
@@ -195,22 +195,14 @@
   char *comma = ", ";
   char *sep = "(";
 
-  if (buf->StatMask & STAT_PREBUFFERING) {
+  if (buf->prebuffering) {
     cur += sprintf (cur, "%sPrebuffering", sep);
     sep = comma;
   }
-  if (!buf->Playing) {
+  if (buf->paused) {
     cur += sprintf (cur, "%sPaused", sep);
     sep = comma;
   }
-  if (buf->FlushPending) {
-    cur += sprintf (cur, "%sFlushing", sep);
-    sep = comma;
-  }
-  if (buf->StatMask & STAT_INACTIVE) {
-    cur += sprintf (cur, "%sInactive", sep);
-    sep = comma;
-  }
   if (buf->eos) {
     cur += sprintf (cur, "%sEOS", sep);
     sep = comma;
@@ -263,12 +255,14 @@
   size_t origSize;
   unsigned char *data = ptr;
 
-  size *= nmemb;
   origSize = size;
+  size *= nmemb;
   
   SetTime (Options.statOpts.stats, cursample);
   Ogg123UpdateStats();
-  cursample += Options.playOpts.nth * size * nmemb / Options.outputOpts.channels / 2 / Options.playOpts.ntimes; /* locked to 16-bit */
+  cursample += Options.playOpts.nth * size / Options.outputOpts.channels / 2 / Options.playOpts.ntimes; /* locked to 16-bit */
+  //  fprintf(stderr, "nmemb = %d, size = %d, cursample = %lld\n", nmemb, size,
+  //  cursample);
 
   /* optimized fast path */
   if (curBuffered == BUFFER_CHUNK_SIZE && curBuffered == 0)
@@ -422,7 +416,8 @@
                 Error ("=== No such device %s.\n", optarg);
                 exit(1);
             }
-	    current = append_device(Options.outputOpts.devices, temp_driver_id, 
+	    current = append_device(Options.outputOpts.devices,
+				    temp_driver_id, 
                                     NULL, NULL);
             if(Options.outputOpts.devices == NULL)
                     Options.outputOpts.devices = current;
@@ -535,10 +530,9 @@
     if (Options.outputOpts.BufferSize)
       {
         Options.outputOpts.BufferSize *= 1024;
-	Options.outputOpts.Prebuffer = (Options.outputOpts.Prebuffer * (float) Options.outputOpts.BufferSize / 100.0f);
-	Options.outputOpts.buffer = StartBuffer (Options.outputOpts.BufferSize, (int) Options.outputOpts.Prebuffer,
-					     NULL, (pWriteFunc) OutBufferWrite,
-					     NULL, NULL, 4096);
+	Options.outputOpts.Prebuffer = Options.outputOpts.Prebuffer * 
+	  (float) Options.outputOpts.BufferSize / 100.0f;
+	Options.outputOpts.buffer = buffer_create(Options.outputOpts.BufferSize, (int) Options.outputOpts.Prebuffer, NULL, (pWriteFunc) OutBufferWrite, NULL, NULL, 4096);
         Options.statOpts.stats[8].enabled = 1;
         Options.statOpts.stats[9].enabled = 1;
       }
@@ -569,7 +563,7 @@
     }
 
     if (Options.outputOpts.buffer != NULL) {
-      buffer_WaitForEmpty (Options.outputOpts.buffer);
+      buffer_wait_for_empty (Options.outputOpts.buffer);
     }
     
     exit (0);
@@ -606,11 +600,11 @@
   case SIGINT:
     exit_requested = 1;
     if (Options.outputOpts.buffer)
-      buffer_flush (Options.outputOpts.buffer);
+      buffer_thread_kill (Options.outputOpts.buffer);
     break;
   case SIGTSTP:
     if (Options.outputOpts.buffer) {
-      buffer_KillBuffer (Options.outputOpts.buffer, SIGSTOP);
+      buffer_thread_pause (Options.outputOpts.buffer);
     }
     kill (getpid(), SIGSTOP);
     /* buffer_Pause (Options.outputOpts.buffer);
@@ -629,7 +623,7 @@
     break;
   case SIGCONT:
     if (Options.outputOpts.buffer)
-      buffer_KillBuffer (Options.outputOpts.buffer, SIGCONT);
+      buffer_thread_unpause (Options.outputOpts.buffer);
     break;
   default:
     psignal (signo, "Unknown signal caught");
@@ -713,10 +707,7 @@
       signal(SIGALRM,signal_activate_skipfile);
       alarm(Options.playOpts.delay);
     }
-    
-    if (Options.outputOpts.buffer)
-      buffer_NewStream (Options.outputOpts.buffer);
-    
+        
     exit_requested = 0;
     
     while (!eof && !exit_requested) {
@@ -772,6 +763,11 @@
       else
         Options.inputOpts.seekable = 0;
 
+      /* Ready to start sending data to the audio playback thread */
+
+      if (Options.outputOpts.buffer)
+	buffer_thread_start (Options.outputOpts.buffer);
+
       eos = 0;
       
       while (!eos && !exit_requested) {
@@ -782,8 +778,7 @@
           signal(SIGALRM,signal_activate_skipfile);
           alarm(Options.playOpts.delay);
           if (Options.outputOpts.buffer) {
-	    buffer_MarkEOS (Options.outputOpts.buffer);
-	    buffer_flush (Options.outputOpts.buffer);
+	    buffer_thread_kill (Options.outputOpts.buffer);
           }
           break;
         }
@@ -813,7 +808,8 @@
           do {
             if (nthc-- == 0) {
               if (Options.outputOpts.buffer) {
-		SubmitData (Options.outputOpts.buffer, convbuffer, ret, 1);
+		buffer_submit_data (Options.outputOpts.buffer, 
+				    convbuffer, ret, 1);
                 Ogg123UpdateStats();
               }
               else
@@ -823,45 +819,16 @@
           } while (++ntimesc < Options.playOpts.ntimes);
           ntimesc = 0;
           
-#if 0
-	  /* old status code */
-	  if (ov_seekable (&vf)) {
-	    u_pos = ov_time_tell(&vf);
-	    c_min = (long) u_pos / (long) 60;
-	    c_sec = u_pos - 60 * c_min;
-	    r_min = (long) (u_time - u_pos) / (long) 60;
-	    r_sec = (u_time - u_pos) - 60 * r_min;
-	    if (Options.outputOpts.buffer)
-	      fprintf(stderr,
-		      "\rTime: %02li:%05.2f [%02li:%05.2f] of %02li:%05.2f, Bitrate: %5.1f, Buffer fill: %3.0f%%   \r",
-		      c_min, c_sec, r_min, r_sec, t_min, t_sec,
-		      (double) ov_bitrate_instant(&vf) / 1000.0F,
-		      (double) buffer_full(Options.outputOpts.buffer) / (double) Options.outputOpts.buffer->size * 100.0F);
-	    else
-	      fprintf(stderr,
-		      "\rTime: %02li:%05.2f [%02li:%05.2f] of %02li:%05.2f, Bitrate: %5.1f   \r",
-		      c_min, c_sec, r_min, r_sec, t_min, t_sec,
-		      (double) ov_bitrate_instant(&vf) / 1000.0F);
-	  } else {
-	    /* working around a bug in vorbisfile */
-	    u_pos = (double) ov_pcm_tell(&vf) / (double) vi->rate;
-	    c_min = (long) u_pos / (long) 60;
-	    c_sec = u_pos - 60 * c_min;
-	    if (Options.outputOpts.buffer)
-	      fprintf(stderr,
-		      "\rTime: %02li:%05.2f, Bitrate: %5.1f, Buffer fill: %3.0f%%   \r",
-		      c_min, c_sec,
-		      (float) ov_bitrate_instant (&vf) / 1000.0F,
-		      (double) buffer_full(Options.outputOpts.buffer) / (double) Options.outputOpts.buffer->size * 100.0F);
-	    else
-	      fprintf(stderr,
-		      "\rTime: %02li:%05.2f, Bitrate: %5.1f   \r",
-		      c_min, c_sec,
-		      (float) ov_bitrate_instant (&vf) / 1000.0F);
-	  }
-#endif
         }
       }
+
+      /* Done playing this logical bitstream.  Now we cleanup. */
+      if (Options.outputOpts.buffer) {
+	buffer_mark_eos (Options.outputOpts.buffer);
+	buffer_wait_for_empty (Options.outputOpts.buffer);
+	buffer_thread_kill (Options.outputOpts.buffer);
+      }
+
     }
     
     alarm(0);
@@ -870,11 +837,6 @@
     
     ov_clear(&vf);
     
-    if (Options.outputOpts.buffer) {
-      buffer_MarkEOS (Options.outputOpts.buffer);
-      buffer_WaitForEmpty (Options.outputOpts.buffer);
-    }
-
     ShowMessage (1, 1, 1, "Done.");
     
     if (exit_requested)
@@ -892,9 +854,6 @@
   
   if(prevrate !=0 && prevchan!=0 && Options.outputOpts.devicesOpen)
     {
-      if (Options.outputOpts.buffer)
-	buffer_WaitForEmpty (Options.outputOpts.buffer);
-      
       close_audio_devices (Options.outputOpts.devices);
       Options.outputOpts.devicesOpen = 0;
     }
@@ -972,7 +931,7 @@
   }
       
   if (Options.outputOpts.buffer) {
-    buffer_cleanup (Options.outputOpts.buffer);
+    buffer_destroy (Options.outputOpts.buffer);
     Options.outputOpts.buffer = NULL;
   }
 

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