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

Kenneth C. Arnold kcarnold at xiph.org
Sat Aug 11 20:59:34 PDT 2001



kcarnold    01/08/11 20:59:34

  Modified:    ogg123   Tag: kcarnold_work Makefile.am ao_interface.c
                        buffer.c buffer.h curl_interface.c curl_interface.h
                        ogg123.c ogg123.h
  Added:       ogg123   Tag: kcarnold_work options.c options.h status.c
                        status.h
  Log:
  All in a day's work:
  
  - new options system. way, way, way more flexible than before. Fun stuff.
  - new status system. not used yet.
  - fixed a few segfaults
  - handled many, many more boundary conditions; if there's a deadlock still
    there, please tell me so I can sleep well.
  - restructured a few little things, still need to restructure more
  
  Playlists are coming. It's on my list for pre-rc2.
  
  Please, anyone on the CVS list, test out this branch! And I still need curl
  autoconf magic.

Revision  Changes    Path
No                   revision

No                   revision

1.14.2.4  +2 -3      vorbis-tools/ogg123/Makefile.am

Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/Makefile.am,v
retrieving revision 1.14.2.3
retrieving revision 1.14.2.4
diff -u -r1.14.2.3 -r1.14.2.4
--- Makefile.am	2001/08/11 02:10:09	1.14.2.3
+++ Makefile.am	2001/08/12 03:59:31	1.14.2.4
@@ -13,9 +13,8 @@
 ogg123_LDADD = @VORBISFILE_LIBS@ @VORBIS_LIBS@ @OGG_LIBS@ @AO_LIBS@ \
                 @SOCKET_LIBS@ -lcurl
 
-ogg123_SOURCES = ogg123.c ao_interface.c buffer.c ogg123.h buffer.h getopt.c getopt1.c getopt.h ao_interface.h curl_interface.c curl_interface.h
-## Comment the above and uncomment the next line to disable the buffer support
-##ogg123_SOURCES = ogg123.c ao_interface.c nullbuffer.c ogg123.h buffer.h getopt.c getopt1.c getopt.h
+ogg123_SOURCES = ogg123.c ao_interface.c buffer.c getopt.c getopt1.c curl_interface.c options.c status.c \
+	         ogg123.h ao_interface.h buffer.h getopt.h           curl_interface.h options.h status.h
 
 EXTRA_DIST = $(man_MANS) $(doc_DATA)
 

1.5.2.5   +2 -2      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.4
retrieving revision 1.5.2.5
diff -u -r1.5.2.4 -r1.5.2.5
--- ao_interface.c	2001/08/11 02:55:37	1.5.2.4
+++ ao_interface.c	2001/08/12 03:59:31	1.5.2.5
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: ao_interface.c,v 1.5.2.4 2001/08/11 02:55:37 kcarnold Exp $
+ last mod: $Id: ao_interface.c,v 1.5.2.5 2001/08/12 03:59:31 kcarnold Exp $
 
  ********************************************************************/
 
@@ -146,7 +146,7 @@
   }
 }
 
-void ao_atexit (int exitcode, void *arg)
+void ao_onexit (int exitcode, void *arg)
 {
   devices_t *devices = (devices_t *) arg;
 

1.7.2.11  +95 -35    vorbis-tools/ogg123/buffer.c

Index: buffer.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/buffer.c,v
retrieving revision 1.7.2.10
retrieving revision 1.7.2.11
diff -u -r1.7.2.10 -r1.7.2.11
--- buffer.c	2001/08/11 16:04:21	1.7.2.10
+++ buffer.c	2001/08/12 03:59:31	1.7.2.11
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: buffer.c,v 1.7.2.10 2001/08/11 16:04:21 kcarnold Exp $
+ last mod: $Id: buffer.c,v 1.7.2.11 2001/08/12 03:59:31 kcarnold Exp $
 
  ********************************************************************/
 
@@ -25,7 +25,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/time.h>
-#include <unistd.h> /* for fork and pipe*/
+#include <string.h>
 #include <fcntl.h>
 #include <signal.h>
 
@@ -38,9 +38,9 @@
 
 #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=%d\n", buf->reader, buf->writer, buf->buffer, buf->end, buf->curfill); } while (0)
+#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)
 #else
 #define DEBUG0(x)
 #define DEBUG1(x, y)
@@ -60,11 +60,28 @@
     }
 }
 
+void UnPrebuffer (buf_t * buf)
+{
+  LOCK_MUTEX (buf->StatMutex);
+  buf->StatMask &= ~STAT_PREBUFFERING;
+  UNLOCK_MUTEX (buf->StatMutex);
+  pthread_cond_signal (&buf->DataReadyCondition);
+}
+
+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);
+}
+
 void PthreadCleanup (void *arg)
 {
   buf_t *buf = (buf_t*) arg;
   
   DEBUG0("PthreadCleanup");
+#if 0
   UNLOCK_MUTEX (buf->SizeMutex);
   UNLOCK_MUTEX (buf->StatMutex);
 
@@ -74,6 +91,7 @@
   pthread_cond_broadcast (&buf->OverflowCondition);
   UNLOCK_MUTEX (buf->SizeMutex);
   UNLOCK_MUTEX (buf->StatMutex);
+#endif
 }
 
 void* BufferFunc (void *arg)
@@ -119,17 +137,38 @@
       assert (buf->reader >= buf->buffer);
       assert (buf->reader <= buf->end);
 
+      if (buf->FlushPending)
+	{
+	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;
+	  LOCK_MUTEX (buf->SizeMutex);
+	}
+
       if (buf->curfill == 0) {
         UNLOCK_MUTEX (buf->SizeMutex);
         DEBUG0 ("signalling buffer underflow");
         pthread_cond_signal (&buf->UnderflowCondition);
         LOCK_MUTEX (buf->SizeMutex);
         Prebuffer (buf);
+	if (buf->FlushPending)
+	  goto flushing;
         DEBUG0 ("waiting on data ready");
         pthread_cond_wait (&buf->DataReadyCondition, &buf->SizeMutex);
         goto checkPlaying;
       }
 
+      iseos = 0;
+
       if (buf->reader < buf->writer)
         {
           /* we have all the way to buf->end: 
@@ -176,9 +215,22 @@
 
       DEBUG0("incrementing pointer");
       LOCK_MUTEX (buf->SizeMutex);
-      buf->writer = NewWriterPtr;
-      vbuf->curfill -= WriteThisTime;
-      UNLOCK_MUTEX (buf->SizeMutex);
+      if (vbuf->curfill == 0)
+	{
+	  /* 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);
+	}
+      else
+	{
+	  buf->writer = NewWriterPtr;
+	  vbuf->curfill -= WriteThisTime;
+	  UNLOCK_MUTEX (buf->SizeMutex);
+	}
 
       /* slight abuse of the DataReady condition, but makes sense. */
       DEBUG0 ("signalling buffer no longer full");
@@ -191,8 +243,8 @@
 }
 
 buf_t *StartBuffer (long size, long prebuffer, void *data, 
-		    size_t (*write_func) (void *, size_t, size_t, void *, char),
-		    void *initData, int (*init_func) (void*), int OptimalWriteSize)
+		    pWriteFunc write_func, void *initData, 
+		    pInitFunc init_func, int OptimalWriteSize)
 {
   buf_t *buf = malloc (sizeof(buf_t) + sizeof (chunk) * (size - 1));
 
@@ -220,7 +272,7 @@
   buf->init_func = init_func;
 
   buf->reader = buf->writer = buf->buffer;
-  buf->end = buf->buffer + (size - 1);
+  buf->end = buf->buffer + size;
   buf->OptimalWriteSize = OptimalWriteSize;
   buf->size = size;
   buf->prebuffer = prebuffer;
@@ -247,8 +299,10 @@
   DUMP_BUFFER_INFO(buf);
 
   /* wait on buffer overflow */
-  while (buf->curfill + size > buf->size)
+  while (buf->curfill + size > buf->size) {
+    UnPrebuffer (buf);
     pthread_cond_wait (&buf->DataReadyCondition, &buf->SizeMutex);
+  }
 
   DEBUG0("writing chunk into buffer");
   buf->curfill += size;
@@ -276,12 +330,9 @@
   UNLOCK_MUTEX (buf->SizeMutex);
 
   if ((buf->StatMask & STAT_PREBUFFERING)
-      && buf->curfill >= buf->prebuffer) {
+      && buf->curfill + 1 >= buf->prebuffer) {
     DEBUG0("prebuffering done, starting writer");
-    LOCK_MUTEX (buf->StatMutex);
-    buf->StatMask &= ~STAT_PREBUFFERING;
-    UNLOCK_MUTEX (buf->StatMutex);
-    pthread_cond_signal (&buf->DataReadyCondition);
+    UnPrebuffer (buf);
   }
   else if (PrevSize == 0)
     pthread_cond_signal (&buf->DataReadyCondition);
@@ -300,38 +351,34 @@
   }
 }
 
+/* this is the only function here that may be called from
+ * a signal handler. */
 void buffer_flush (buf_t *buf)
 {
   DEBUG0("flush buffer");
-  LOCK_MUTEX (buf->SizeMutex);
-  buf->curfill = 0;
-  buf->reader = buf->writer;
-  UNLOCK_MUTEX (buf->SizeMutex);
-  Prebuffer (buf);
+  buf->FlushPending = 1;
+  if (!buf->BufferThread)
+    buf->curfill = 0;
+  DEBUG0("flush buffer done");
 }
 
 void buffer_WaitForEmpty (buf_t *buf)
 {
   DEBUG0("waiting for empty");
-  LOCK_MUTEX (buf->SizeMutex);
+  DUMP_BUFFER_INFO(buf);
+  UnPrebuffer (buf);
+  DEBUG0("unprebuffered");
+  SignalAll (buf);
+  DEBUG0("signalled all");
+  LOCK_MUTEX(buf->SizeMutex);
   while (buf->curfill > 0)
     pthread_cond_wait (&buf->UnderflowCondition, &buf->SizeMutex);
+  DEBUG0("done waiting");
   UNLOCK_MUTEX (buf->SizeMutex);
+  DEBUG0("buffer empty");
   Prebuffer (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;
-  }
-  DEBUG0("buffer done.");
-}
-
 long buffer_full (buf_t* buf) {
   return buf->curfill;
 }
@@ -359,8 +406,21 @@
 void buffer_MarkEOS (buf_t *buf)
 {
   buf->eos = 1;
+  UnPrebuffer (buf);
+  pthread_cond_signal (&buf->DataReadyCondition);
 }
 
+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;
+  }
+  DEBUG0("buffer done.");
+}
 
 void buffer_cleanup (buf_t *buf) {
   if (buf) {

1.2.2.11  +8 -5      vorbis-tools/ogg123/buffer.h

Index: buffer.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/buffer.h,v
retrieving revision 1.2.2.10
retrieving revision 1.2.2.11
diff -u -r1.2.2.10 -r1.2.2.11
--- buffer.h	2001/08/11 16:04:22	1.2.2.10
+++ buffer.h	2001/08/12 03:59:31	1.2.2.11
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
  
- last mod: $Id: buffer.h,v 1.2.2.10 2001/08/11 16:04:22 kcarnold Exp $
+ last mod: $Id: buffer.h,v 1.2.2.11 2001/08/12 03:59:31 kcarnold Exp $
  
 ********************************************************************/
 
@@ -23,15 +23,17 @@
 #include <pthread.h>
 
 typedef unsigned char chunk; /* sizeof (chunk) must be 1; if you need otherwise it's not hard to fix */
+typedef size_t (*pWriteFunc) (void *, size_t, size_t, void *, char);
+typedef int (*pInitFunc) (void *);
 
 typedef struct buf_s
 {
   /* generic buffer interface */
   void * data;
-  size_t (*write_func) (chunk *ptr, size_t size, size_t nmemb, void * d, char iseos);
+  pWriteFunc write_func;
 
   void * initData;
-  int (*init_func) (void *);
+  pInitFunc init_func;
   
   /* pthreads variables */
   pthread_t BufferThread;
@@ -43,6 +45,7 @@
   
   /* the buffer itself */
   char StatMask;
+  char FlushPending; /* must be separate from statmask */
   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 */
@@ -59,8 +62,8 @@
 #define STAT_EMPTYING 4
 
 buf_t *StartBuffer (long size, long prebuffer, void *data, 
-		    size_t (*write_func) (void *, size_t, size_t, void *, char),
-		    void *initData, int (*init_func) (void*), int OptimalWriteSize);
+		    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_shutdown (buf_t *buf);

1.1.2.4   +25 -11    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.3
retrieving revision 1.1.2.4
diff -u -r1.1.2.3 -r1.1.2.4
--- curl_interface.c	2001/08/11 16:04:22	1.1.2.3
+++ curl_interface.c	2001/08/12 03:59:31	1.1.2.4
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
  
- last mod: $Id: curl_interface.c,v 1.1.2.3 2001/08/11 16:04:22 kcarnold Exp $
+ last mod: $Id: curl_interface.c,v 1.1.2.4 2001/08/12 03:59:31 kcarnold Exp $
  
 ********************************************************************/
 
@@ -19,7 +19,8 @@
 
 #include <stdlib.h>
 #include <stdio.h>
-#include <signal.h>		/* for SIGTERM */
+#include <string.h> /* for memmove */
+#include <signal.h>		/* for SIGINT */
 
 #define DEBUG_CURLINTERFACE
 
@@ -47,7 +48,7 @@
          data->BytesRequested);
 
   pthread_mutex_lock (&data->ReadDataMutex);
-  while (data->BytesRequested == 0)
+  while (data->BytesRequested == 0 && !data->ShuttingDown)
     pthread_cond_wait (&data->ReadRequestedCondition, &data->ReadDataMutex);
 
   data->EOS = iseos;
@@ -158,7 +159,7 @@
 buf_t *
 InitStream (InputOpts_t inputOpts)
 {
-  StreamInputBufferData_t *data = malloc (sizeof (StreamInputBufferData_t));
+  StreamInputBufferData_t *data = calloc (1, sizeof (StreamInputBufferData_t));
   buf_t *buf;
 
   debug ("InitStream\n");
@@ -197,6 +198,10 @@
   debug (" set curl opts\n");
   CurlSetopts (data->CurlHandle, buf, inputOpts);
 
+  debug (" init saving stream\n");
+  if (inputOpts.SaveStream)
+    data->SavedStream = fopen (inputOpts.SaveStream, "wb");
+
   pthread_create (&data->CurlThread, NULL, CurlGo, buf);
 
   debug ("returning.\n");
@@ -204,7 +209,7 @@
 }
 
 size_t
-StreamBufferRead (void *ptr, size_t size, size_t nmemb, void *arg)
+_StreamBufferRead (void *ptr, size_t size, size_t nmemb, void *arg)
 {
   StreamInputBufferData_t *data = arg;
   size_t ret;
@@ -263,6 +268,15 @@
   return ret;
 }
 
+size_t StreamBufferRead (void *ptr, size_t size, size_t nmemb, void *arg)
+{
+  StreamInputBufferData_t *data = arg;
+  size_t ret = _StreamBufferRead (ptr, size, nmemb, arg);
+  if (data->SavedStream)
+    fwrite (ptr, ret, 1, data->SavedStream);
+  return ret;
+}
+
 /* These are no-ops for now. */
 int
 StreamBufferSeek (void *arg, ogg_int64_t offset, int whence)
@@ -271,20 +285,19 @@
   return -1;
 }
 
-void StreamInputDataCleanup (StreamInputBufferData_t *data)
-{
-}
-
 int
 StreamBufferClose (void *arg)
 {
   StreamInputBufferData_t *data = arg;
 
-  debug ("StreamBufferClose");
+  debug ("StreamBufferClose\n");
   if (data)
     {
       pthread_kill (data->CurlThread, SIGTERM);
       pthread_join (data->CurlThread, NULL);
+      data->ShuttingDown = 1;
+      data->BytesRequested = 0;
+      pthread_cond_signal (&data->ReadRequestedCondition);
       memset (data, 0, sizeof(data));
       free (data);
     }
@@ -299,7 +312,8 @@
 
 void StreamInputCleanup (buf_t *buf)
 { 
-  StreamInputDataCleanup (buf->data);
+  StreamBufferClose (buf->data);
+  buf->data = 0;
   buffer_flush (buf);
   buffer_cleanup (buf);
 }

1.1.2.4   +6 -2      vorbis-tools/ogg123/Attic/curl_interface.h

Index: curl_interface.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/Attic/curl_interface.h,v
retrieving revision 1.1.2.3
retrieving revision 1.1.2.4
diff -u -r1.1.2.3 -r1.1.2.4
--- curl_interface.h	2001/08/11 16:04:22	1.1.2.3
+++ curl_interface.h	2001/08/12 03:59:31	1.1.2.4
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
  
- last mod: $Id: curl_interface.h,v 1.1.2.3 2001/08/11 16:04:22 kcarnold Exp $
+ last mod: $Id: curl_interface.h,v 1.1.2.4 2001/08/12 03:59:31 kcarnold Exp $
  
 ********************************************************************/
 
@@ -29,6 +29,8 @@
   /* Input buffer options */
   long BufferSize;
   long Prebuffer;
+
+  char *SaveStream;
   
   /* libcurl options */
   char *URL;
@@ -54,12 +56,14 @@
   CURL * CurlHandle;
 
   char EOS;
+  char ShuttingDown;
 
   size_t BytesRequested;
   unsigned char *WriteTarget;
   unsigned char *CurWritePtr;
   unsigned char ExcessData[VORBIS_CHUNKIN_SIZE];
   int ExcessDataSize;
+  FILE *SavedStream;
 } StreamInputBufferData_t;
 
 buf_t *InitStream (InputOpts_t inputOpts);
@@ -67,6 +71,6 @@
 int StreamBufferSeek (void *arg, ogg_int64_t offset, int whence);
 int StreamBufferClose (void *arg);
 long StreamBufferTell (void *arg);
-void StreamBufferCleanup (buf_t *buf);
+void StreamInputCleanup (buf_t *buf);
 
 #endif /* __CURL_INTERFACE_H */

1.39.2.13 +235 -226  vorbis-tools/ogg123/ogg123.c

Index: ogg123.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.c,v
retrieving revision 1.39.2.12
retrieving revision 1.39.2.13
diff -u -r1.39.2.12 -r1.39.2.13
--- ogg123.c	2001/08/11 16:04:22	1.39.2.12
+++ ogg123.c	2001/08/12 03:59:31	1.39.2.13
@@ -14,7 +14,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: ogg123.c,v 1.39.2.12 2001/08/11 16:04:22 kcarnold Exp $
+ last mod: $Id: ogg123.c,v 1.39.2.13 2001/08/12 03:59:31 kcarnold Exp $
 
  ********************************************************************/
 
@@ -22,18 +22,18 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
 #include <errno.h>
 #include <time.h>
 #include <getopt.h>
 #include <signal.h>
+#include <unistd.h>
 
 #include "ogg123.h"
 #include "ao_interface.h"
 #include "curl_interface.h"
 #include "buffer.h"
+#include "options.h"
+#include "status.h"
 
 /* take buffer out of the data segment, not the stack */
 #define BUFFER_CHUNK_SIZE 4096
@@ -43,6 +43,7 @@
 buf_t * OutBuffer = NULL;
 
 static char skipfile_requested;
+static char exit_requested;
 
 struct {
     char *key;			/* includes the '=' for programming convenience */
@@ -63,84 +64,151 @@
 };
 
 struct option long_options[] = {
+  /* GNU standard options */
     {"help", no_argument, 0, 'h'},
     {"version", no_argument, 0, 'V'},
+    /* ogg123-specific options */
+    {"buffer", required_argument, 0, 'b'},
+    {"config", optional_argument, 0, 'c'},
     {"device", required_argument, 0, 'd'},
     {"file", required_argument, 0, 'f'},
     {"skip", required_argument, 0, 'k'},
+    {"delay", required_argument, 0, 'l'},
     {"device-option", required_argument, 0, 'o'},
-    {"verbose", no_argument, 0, 'v'},
-    {"quiet", no_argument, 0, 'q'},
-    {"shuffle", no_argument, 0, 'z'},
-    {"buffer", required_argument, 0, 'b'},
     {"prebuffer", required_argument, 0, 'p'},
-    {"delay", required_argument, 0, 'l'},
+    {"quiet", no_argument, 0, 'q'},
+    {"save", required_argument, 0, 's'},
+    {"verbose", no_argument, 0, 'v'},
     {"nth", required_argument, 0, 'x'},
     {"ntimes", required_argument, 0, 'y'},
+    {"shuffle", no_argument, 0, 'z'},
     {0, 0, 0, 0}
 };
 
+int ConfigErrorFunc (void *arg, ParseCode pcode, int lineno, char *filename, char *line)
+{
+  if (pcode == parse_syserr)
+    {
+      if (errno != EEXIST && errno != ENOENT)
+	perror ("System error");
+      return -1;
+    }
+  else
+    {
+      fprintf (stderr, "Parse error: %s on line %d of %s (%s)\n", ParseErr(pcode), lineno, filename, line);
+      return 0;
+    }
+}
+
+ParseCode ReadConfig (Option_t opts[], char *filename)
+{
+  return ParseFile (opts, filename, ConfigErrorFunc, NULL);
+}
+
+void ReadStdConfigs (Option_t opts[])
+{
+  char filename[FILENAME_MAX];
+  char *homedir = getenv("HOME");
+
+  /* Read config from files in same order as original parser */
+  if (homedir && strlen(homedir) < FILENAME_MAX - 10) {
+    /* Try ~/.ogg123 */
+    strncpy (filename, homedir, FILENAME_MAX);
+    strcat (filename, "/.ogg123rc");
+    ReadConfig (opts, filename);
+  }
+  ReadConfig (opts, "/etc/ogg123rc");
+}
+
 void usage(void)
 {
-    FILE *o = stderr;
-    int i, driver_count;
-    ao_info **devices = ao_driver_info_list(&driver_count);
-
-    fprintf(o,
-	    "Ogg123 from " PACKAGE " " VERSION "\n"
-	    " by Kenneth Arnold <kcarnold at arnoldnet.net> and others\n\n"
-	    "Usage: ogg123 [<options>] <input file> ...\n\n"
-	    "  -h, --help     this help\n"
-	    "  -V, --version  display Ogg123 version\n"
-	    "  -d, --device=d uses 'd' as an output device\n"
-	    "      Possible devices are:\n"
-	    "        ");
-
-    for(i = 0; i < driver_count; i++)
-      fprintf(o,"%s ",devices[i]->short_name);
-
-    fprintf(o,"\n");
-
-    fprintf(o,
-	    "  -f, --file=filename  Set the output filename for a previously\n"
-	    "      specified file device (with -d).\n"
-	    "  -k n, --skip n  Skip the first 'n' seconds\n"
-	    "  -o, --device-option=k:v passes special option k with value\n"
-	    "      v to previously specified device (with -d).  See\n"
-	    "      man page for more info.\n"
-	    "  -b n, --buffer n  use a buffer of approximately 'n' kilobytes\n"
-	    "  -p n, --prebuffer n  prebuffer n% of the buffer before playing\n"
-	    "  -v, --verbose  display progress and other useful stuff\n"
-	    "  -q, --quiet    don't display anything (no title)\n"
-	    "  -z, --shuffle  shuffle play\n"
-	    "\n"
-	    "ogg123 will skip to the next song on SIGINT (Ctrl-C) after s seconds after\n"
-	    "song start."
-	    "  -l, --delay=s  set s (default 1). If s=-1, disable song skip.\n");
+  FILE *o = stderr;
+  int i, driver_count;
+  ao_info **devices = ao_driver_info_list(&driver_count);
+  
+  fprintf(o,
+	  "Ogg123 from " PACKAGE " " VERSION "\n"
+	  " by Kenneth Arnold <kcarnold at arnoldnet.net> and others\n\n"
+	  "Usage: ogg123 [<options>] <input file> ...\n\n"
+	  "  -h, --help     this help\n"
+	  "  -V, --version  display Ogg123 version\n"
+	  "  -d, --device=d uses 'd' as an output device\n"
+	  "      Possible devices are:\n"
+	  "        ");
+  
+  for(i = 0; i < driver_count; i++)
+    fprintf(o,"%s ",devices[i]->short_name);
+  
+  fprintf(o,"\n");
+  
+  fprintf(o,
+	  "  -f, --file=filename  Set the output filename for a previously\n"
+	  "      specified file device (with -d).\n"
+	  "  -k n, --skip n  Skip the first 'n' seconds\n"
+	  "  -o, --device-option=k:v passes special option k with value\n"
+	  "      v to previously specified device (with -d).  See\n"
+	  "      man page for more info.\n"
+	  "  -b n, --buffer n  use a buffer of approximately 'n' kilobytes\n"
+	  "  -p n, --prebuffer n  prebuffer n%% of the buffer before playing\n"
+	  "  -v, --verbose  display progress and other status information\n"
+	  "  -q, --quiet    don't display anything (no title)\n"
+	  "  -z, --shuffle  shuffle play\n"
+	  "\n"
+	  "ogg123 will skip to the next song on SIGINT (Ctrl-C) after s seconds after\n"
+	  "song start.\n"
+	  "  -l, --delay=s  set s (default 1). If s=-1, disable song skip.\n");
 }
 
 int main(int argc, char **argv)
 {
-    ogg123_options_t opt;
-    int ret;
-    int option_index = 1;
-    ao_option *temp_options = NULL;
-    ao_option ** current_options = &temp_options;
-    ao_info *info;
-    int temp_driver_id = -1;
-    devices_t *current;
-
-    memset (&opt, 0, sizeof(opt));
-
-    opt.delay = 1;
-    opt.nth = 1;
-    opt.ntimes = 1;
-
-    on_exit (ogg123_onexit, &opt);
-    signal (SIGINT, signal_quit);
-    ao_initialize();
+  ogg123_options_t opt;
+  int ret;
+  int option_index = 1;
+  ao_option *temp_options = NULL;
+  ao_option ** current_options = &temp_options;
+  ao_info *info;
+  int temp_driver_id = -1;
+  devices_t *current;
+
+  /* data used just to initialize the pointers */
+  char char_n = 'n';
+  long int_10000 = 10000;
+  float float_50f = 50.0f;
+  float float_0f = 0.0f;
+  long int_1 = 1;
+  long int_0 = 0;
+
+  /* *INDENT-OFF* */
+  Option_t opts[] = {
+    /* found, name, description, type, ptr, default */
+    {0, "default_device", "default output device", opt_type_string, &opt.default_device, NULL},
+    {0, "shuffle",        "shuffle playlist",      opt_type_char,   &opt.shuffle,        &char_n},
+    {0, "verbose",        "be verbose",            opt_type_int,    &opt.verbose,        &int_0},
+    {0, "quiet",          "be quiet",              opt_type_int,    &opt.quiet,          &int_0},
+    {0, "outbuffer",      "out buffer size (kB)",  opt_type_int,    &opt.outbuffer_size, &int_0},
+    {0, "outprebuffer",   "out prebuffer (%)",     opt_type_float,  &opt.outprebuffer,   &float_0f},
+    {0, "inbuffer",       "in buffer size (kB)",   opt_type_int,    &opt.inputOpts.BufferSize, &int_10000},
+    {0, "inprebuffer",    "in prebuffer (%)",      opt_type_float,  &opt.inputOpts.Prebuffer, &float_50f},
+    {0, "save_stream",    "append stream to file", opt_type_string, &opt.inputOpts.SaveStream, NULL},
+    {0, "delay",          "skip file delay (sec)", opt_type_int,    &opt.delay,          &int_1},
+    {0, NULL,             NULL,                    0,               NULL,                NULL}
+  };
+  /* *INDENT-ON* */
 
-    while (-1 != (ret = getopt_long(argc, argv, "b:d:f:hl:k:o:p:qvVx:y:z",
+  memset (&opt, 0, sizeof(opt));
+  
+  opt.delay = 1;
+  opt.nth = 1;
+  opt.ntimes = 1;
+
+  on_exit (ogg123_onexit, &opt);
+  signal (SIGINT, signal_quit);
+  ao_initialize();
+  
+  InitOpts(opts);
+  ReadStdConfigs (opts);
+
+    while (-1 != (ret = getopt_long(argc, argv, "b:c::d:f:hl:k:o:p:qvVx:y:z",
                                     long_options, &option_index))) {
         switch (ret) {
         case 0:
@@ -148,8 +216,26 @@
                     "Internal error: long option given when none expected.\n");
             exit(1);
         case 'b':
-	  opt.buffer_size = atoi(optarg) * 1024;
+	  opt.outbuffer_size = atoi(optarg);
           break;
+	case 'c':
+	  if (optarg)
+	    {
+	      char *tmp = strdup (optarg);
+	      ParseCode pcode = ParseLine (opts, tmp);
+	      if (pcode != parse_ok)
+		fprintf (stderr,
+			 "Error parsing config option from command line.\n"
+			 "Error: %s\n"
+			 "Option was: %s\n", ParseErr (pcode), optarg);
+	      free (tmp);
+	    }
+	  else {
+	    fprintf (stdout, "Available options:\n");
+	    DescribeOptions (opts, stdout);
+	    exit (0);
+	  }
+	  break;
         case 'd':
             temp_driver_id = ao_driver_id(optarg);
             if (temp_driver_id < 0) {
@@ -189,11 +275,11 @@
             usage();
             exit(0);
         case 'p':
-	  opt.prebuffer = atoi (optarg); /* prebuffer in integer percentage */
-	  if (opt.prebuffer < 0 || opt.prebuffer > 100)
+	  opt.outprebuffer = atof (optarg);
+	  if (opt.outprebuffer < 0.0f || opt.outprebuffer > 100.0f)
             {
               fprintf (stderr, "Prebuffer value invalid. Range is 0-100, using nearest value.\n");
-	      opt.prebuffer = opt.prebuffer < 0 ? 0 : 100;
+	      opt.outprebuffer = opt.outprebuffer < 0.0f ? 0.0f : 100.0f;
             }
           break;
         case 'q':
@@ -229,27 +315,41 @@
 
     /* Add last device to device list or use the default device */
     if (temp_driver_id < 0) {
-	temp_driver_id = get_default_device();
-	if(temp_driver_id < 0) {
-		temp_driver_id = ao_default_driver_id();
-	}
-	if (temp_driver_id < 0) {
-	    fprintf(stderr,
-		    "Could not load default driver and no ~/.ogg123rc found. Exiting.\n");
-	    exit(1);
-	}
-	opt.outdevices = append_device(opt.outdevices, temp_driver_id, 
-				       temp_options, NULL);
+      if (opt.default_device) {
+	temp_driver_id = ao_driver_id (opt.default_device);
+	if (temp_driver_id < 0 && opt.quiet < 2)
+	  fprintf (stderr, "Warning: driver %s specified in configuration file invalid.\n", opt.default_device);
+      }
+    }
+
+    if (temp_driver_id < 0) {
+      temp_driver_id = ao_default_driver_id();
     }
 
-    if (opt.buffer_size)
+    if (temp_driver_id < 0) {
+      fprintf(stderr,
+	      "Could not load default driver and no driver specified in config file. Exiting.\n");
+      exit(1);
+    }
+    opt.outdevices = append_device(opt.outdevices, temp_driver_id, 
+				   temp_options, NULL);
+
+    opt.inputOpts.BufferSize *= 1024;
+
+    if (opt.outbuffer_size)
       {
-	opt.prebuffer = (int) ((double) opt.prebuffer * (double) opt.buffer_size / 100.0F);
-	OutBuffer = StartBuffer (opt.buffer_size, opt.prebuffer,
-				 opt.outdevices, devices_write,
+	opt.outbuffer_size *= 1024;
+	opt.outprebuffer = (opt.outprebuffer * (float) opt.outbuffer_size / 100.0f);
+	OutBuffer = StartBuffer (opt.outbuffer_size, (int) opt.outprebuffer,
+				 opt.outdevices, (pWriteFunc) devices_write,
                                  NULL, NULL, 4096);
       }
     
+    if (opt.shuffle == 'n' || opt.shuffle == 'N')
+      opt.shuffle = 0;
+    else if (opt.shuffle == 'y' || opt.shuffle == 'Y')
+      opt.shuffle = 1;
+
     if (opt.shuffle) {
         int i;
         int range = argc - optind;
@@ -266,7 +366,7 @@
 
     while (optind < argc) {
         opt.read_file = argv[optind];
-	play_file(opt);
+	play_file(&opt);
         optind++;
     }
 
@@ -304,17 +404,21 @@
 
 void signal_quit(int ignored)
 {
-  exit(0);
+  exit_requested = 1;
+  if (OutBuffer)
+    buffer_flush (OutBuffer);
 }
 
+#if 0
 /* from vorbisfile.c */
 static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence)
 {
   if(f==NULL)return(-1);
   return fseek(f,(int)off,whence);
 }
+#endif
 
-void play_file(ogg123_options_t opt)
+void play_file(ogg123_options_t *opt)
 {
   OggVorbis_File vf;
   int current_section = -1, eof = 0, eos = 0, ret;
@@ -322,155 +426,83 @@
   long t_min = 0, c_min = 0, r_min = 0;
   double t_sec = 0, c_sec = 0, r_sec = 0;
   int is_big_endian = ao_is_big_endian();
-  double realseekpos = opt.seekpos;
+  double realseekpos = opt->seekpos;
   int nthc = 0, ntimesc = 0;
   double u_time, u_pos;
   int tmp;
   ov_callbacks VorbisfileCallbacks;
   
-  tmp = strchr(opt.read_file, ':') - opt.read_file;
-  if (tmp < 10 && tmp + 2 < strlen(opt.read_file) && !strncmp(opt.read_file + tmp, "://", 3))
+  tmp = strchr(opt->read_file, ':') - opt->read_file;
+  if (tmp < 10 && tmp + 2 < strlen(opt->read_file) && !strncmp(opt->read_file + tmp, "://", 3))
     {
-      InputOpts_t inputOpts;
-      
       /* let's call this a URL. */
-      if (opt.quiet < 1)
-	fprintf (stderr, "Playing from stream %s\n", opt.read_file);
+      if (opt->quiet < 1)
+	fprintf (stderr, "Playing from stream %s\n", opt->read_file);
       VorbisfileCallbacks.read_func = StreamBufferRead;
       VorbisfileCallbacks.seek_func = StreamBufferSeek;
       VorbisfileCallbacks.close_func = StreamBufferClose;
       VorbisfileCallbacks.tell_func = StreamBufferTell;
       
-      inputOpts.BufferSize = 1024*1024;
-      inputOpts.Prebuffer = 10000;
-      inputOpts.URL = opt.read_file;
-      InBuffer = InitStream (inputOpts);
+      opt->inputOpts.URL = opt->read_file;
+      InBuffer = InitStream (opt->inputOpts);
       if ((ov_open_callbacks (InBuffer->data, &vf, NULL, 0, VorbisfileCallbacks)) < 0) {
-	fprintf(stderr, "E: input not an Ogg Vorbis audio stream.\n");
+	fprintf(stderr, "Error: input not an Ogg Vorbis audio stream.\n");
         return;
       }
       
     }
   else
     {
+#if 0
       VorbisfileCallbacks.read_func = fread;
       VorbisfileCallbacks.seek_func = _fseek64_wrap;
       VorbisfileCallbacks.close_func = fclose;
       VorbisfileCallbacks.tell_func = ftell;
-      if (strcmp(opt.read_file, "-"))
+#endif
+      if (strcmp(opt->read_file, "-"))
         {
-	  if (opt.quiet < 1)
-	    fprintf(stderr, "Playing from file %s.\n", opt.read_file);
+	  if (opt->quiet < 1)
+	    fprintf(stderr, "Playing from file %s.\n", opt->read_file);
           /* Open the file. */
-	  if ((opt.instream = fopen(opt.read_file, "rb")) == NULL) {
+	  if ((opt->instream = fopen(opt->read_file, "rb")) == NULL) {
             fprintf(stderr, "Error opening input file.\n");
             exit(1);
           }
         }
       else
         {
-	  if (opt.quiet < 1)
+	  if (opt->quiet < 1)
             fprintf(stderr, "Playing from standard input.\n");
-	  opt.instream = stdin;
+	  opt->instream = stdin;
         }
-      if ((ov_open_callbacks (opt.instream, &vf, NULL, 0, VorbisfileCallbacks)) < 0) {
-	fprintf(stderr, "E: input not an Ogg Vorbis audio stream.\n");
+      if ((ov_open (opt->instream, &vf, NULL, 0)) < 0) {
+	fprintf(stderr, "Error: input not an Ogg Vorbis audio stream.\n");
         return;
       }
     }
-#if 0
-      /* old stream code */
-    if (strcmp(opt.read_file, "-")) {	/* input file not stdin */
-	if (!strncmp(opt.read_file, "http://", 7)) {
-	    /* Stream down over http */
-	    char *temp = NULL, *server = NULL, *port = NULL, *path = NULL;
-	    int index;
-	    long iport;
-
-	    temp = opt.read_file + 7;
-	    for (index = 0; temp[index] != '/' && temp[index] != ':';
-		 index++);
-	    server = (char *) malloc(index + 1);
-	    strncpy(server, temp, index);
-	    server[index] = '\0';
-
-	    /* Was a port specified? */
-	    if (temp[index] == ':') {
-		/* Grab the port. */
-		temp += index + 1;
-		for (index = 0; temp[index] != '/'; index++);
-		port = (char *) malloc(index + 1);
-		strncpy(port, temp, index);
-		port[index] = '\0';
-		if ((iport = atoi(port)) <= 0 || iport > 65535) {
-		    fprintf(stderr, "%s is not a valid port.\n", port);
-		    exit(1);
-		}
-	    } else
-		iport = 80;
-
-	    path = strdup(temp + index);
-
-	    if ((opt.instream = http_open(server, iport, path)) == NULL) {
-		fprintf(stderr, "Error while connecting to server!\n");
-		exit(1);
-	    }
-	    /* Send HTTP header */
-	    fprintf(opt.instream,
-		    "GET %s HTTP/1.0\r\n"
-		    "Accept: */*\r\n"
-		    "User-Agent: ogg123\r\n"
-		    "Host: %s\r\n\r\n\r\n", path, server);
-
-		fflush(opt.instream); /* Make sure these are all actually sent */
-
-	    /* Dump headers */
-	    {
-		char last = 0, in = 0;
-		int eol = 0;
-
-		if (opt.verbose > 0)
-		  fprintf(stderr, "HTTP Headers:\n");
-		for (;;) {
-		    last = in;
-		    in = getc(opt.instream);
-		    if (opt.verbose > 0)
-		      putc(in, stderr);
-		    if (last == 13 && in == 10) {
-			if (eol)
-			    break;
-			eol = 1;
-		    } else if (in != 10 && in != 13)
-			eol = 0;
-		}
-	    }
-	    free(server);
-	    free(path);
-	} else {
-	}
-    }
-#endif
     
     /* Setup so that pressing ^C in the first second of playback
      * interrupts the program, but after the first second, skips
      * the song.  This functionality is similar to mpg123's abilities. */
     
-    if (opt.delay > 0) {
+    if (opt->delay > 0) {
       skipfile_requested = 0;
       signal(SIGALRM,signal_activate_skipfile);
-      alarm(opt.delay);
+      alarm(opt->delay);
     }
+    
+    exit_requested = 0;
     
-    while (!eof) {
+    while (!eof && !exit_requested) {
       int i;
       vorbis_comment *vc = ov_comment(&vf, -1);
       vorbis_info *vi = ov_info(&vf, -1);
       
-      if(open_audio_devices(&opt, vi->rate, vi->channels) < 0)
+      if(open_audio_devices(opt, vi->rate, vi->channels) < 0)
         exit(1);
 
-	if (opt.quiet < 1) {
-	    if (eos && opt.verbose) fprintf (stderr, "\r                                                                          \r\n");
+	if (opt->quiet < 1) {
+	    if (eos && opt->verbose) fprintf (stderr, "\r                                                                          \r\n");
             for (i = 0; i < vc->comments; i++) {
                 char *cc = vc->user_comments[i];	/* current comment */
                 int i;
@@ -489,11 +521,11 @@
 
             fprintf(stderr, "\nBitstream is %d channel, %ldHz\n",
                     vi->channels, vi->rate);
-	    if (opt.verbose > 1)
+	    if (opt->verbose > 1)
               fprintf(stderr, "Encoded by: %s\n\n", vc->vendor);
         }
 
-	if (opt.verbose > 0 && ov_seekable(&vf)) {
+	if (opt->verbose > 0 && ov_seekable(&vf)) {
             /* Seconds with double precision */
             u_time = ov_time_total(&vf, -1);
             t_min = (long) u_time / (long) 60;
@@ -510,16 +542,15 @@
 
         eos = 0;
 
-	while (!eos) {
+	while (!eos && !exit_requested) {
 
             if (skipfile_requested) {
               eof = eos = 1;
               skipfile_requested = 0;
               signal(SIGALRM,signal_activate_skipfile);
-	      alarm(opt.delay);
-	      if (OutBuffer) {
+	      alarm(opt->delay);
+	      if (OutBuffer)
                 buffer_flush (OutBuffer);
-	      }
               break;
               }
 
@@ -531,7 +562,7 @@
                 /* End of file */
                 eof = eos = 1;
             } else if (ret == OV_HOLE) {
-	      if (opt.verbose > 1) 
+	      if (opt->verbose > 1) 
                 /* we should be able to resync silently; if not there are 
                    bigger problems. */
                 fprintf (stderr, "Warning: hole in the stream; probably harmless\n");
@@ -548,13 +579,13 @@
                     if (OutBuffer)
                         SubmitData (OutBuffer, convbuffer, ret, 1);
                     else
-		      devices_write(convbuffer, ret, 1, opt.outdevices, 0);
-		    nthc = opt.nth - 1;
+		      devices_write(convbuffer, ret, 1, opt->outdevices, 0);
+		    nthc = opt->nth - 1;
                   }
-		} while (++ntimesc < opt.ntimes);
+		} while (++ntimesc < opt->ntimes);
                 ntimesc = 0;
 
-		if (opt.verbose > 0) {
+		if (opt->verbose > 0) {
                     if (ov_seekable (&vf)) {
                       u_pos = ov_time_tell(&vf);
                       c_min = (long) u_pos / (long) 60;
@@ -563,13 +594,13 @@
                       r_sec = (u_time - u_pos) - 60 * r_min;
                       if (OutBuffer)
                         fprintf(stderr,
-				"\rTime: %02li:%05.2f [%02li:%05.2f] of %02li:%05.2f, Bitrate: %.1f, Buffer fill: %3.0f%%   \r",
+				"\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(OutBuffer) / (double) OutBuffer->size * 100.0F);
                       else
                         fprintf(stderr,
-				"\rTime: %02li:%05.2f [%02li:%05.2f] of %02li:%05.2f, Bitrate: %.1f   \r",
+				"\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 {
@@ -580,13 +611,13 @@
                       c_sec = u_pos - 60 * c_min;
                       if (OutBuffer)
                         fprintf(stderr,
-				"\rTime: %02li:%05.2f, Bitrate: %.1f, Buffer fill: %3.0f%%   \r",
+				"\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(OutBuffer) / (double) OutBuffer->size * 100.0F);
                       else
                         fprintf(stderr,
-				"\rTime: %02li:%05.2f, Bitrate: %.1f   \r",
+				"\rTime: %02li:%05.2f, Bitrate: %5.1f   \r",
                                 c_min, c_sec,
                                 (float) ov_bitrate_instant (&vf) / 1000.0F);
                     }
@@ -601,34 +632,13 @@
     
     ov_clear(&vf);
 
-    if (opt.quiet < 1)
+    if (opt->quiet < 1)
         fprintf(stderr, "\nDone.\n");
-}
-
-FILE *http_open(char *server, int port, char *path)
-{
-    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
-    struct hostent *host;
-    struct sockaddr_in sock_name;
-
-    if (sockfd == -1)
-	return NULL;
-
-    if (!(host = gethostbyname(server))) {
-	fprintf(stderr, "Unknown host: %s\n", server);
-	return NULL;
-    }
 
-    memcpy(&sock_name.sin_addr, host->h_addr, host->h_length);
-    sock_name.sin_family = AF_INET;
-    sock_name.sin_port = htons(port);
-
-    if (connect(sockfd, (struct sockaddr *) &sock_name, sizeof(sock_name))) {
-	if (errno == ECONNREFUSED)
-	    fprintf(stderr, "Connection refused\n");
-	return NULL;
-    }
-    return fdopen(sockfd, "r+b");
+    if (exit_requested)
+      {
+	exit (0);
+      }
 }
 
 /* if not for the two lines involving the buffer, this would go in
@@ -725,10 +735,9 @@
   }
       
   if (OutBuffer) {
-    buffer_flush (OutBuffer);
     buffer_cleanup (OutBuffer);
     OutBuffer = NULL;
   }
 
-  ao_atexit (exitcode, opt->outdevices);
+  ao_onexit (exitcode, opt->outdevices);
 }

1.7.2.8   +9 -8      vorbis-tools/ogg123/ogg123.h

Index: ogg123.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.h,v
retrieving revision 1.7.2.7
retrieving revision 1.7.2.8
diff -u -r1.7.2.7 -r1.7.2.8
--- ogg123.h	2001/08/10 16:33:40	1.7.2.7
+++ ogg123.h	2001/08/12 03:59:31	1.7.2.8
@@ -11,7 +11,7 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: ogg123.h,v 1.7.2.7 2001/08/10 16:33:40 kcarnold Exp $
+ last mod: $Id: ogg123.h,v 1.7.2.8 2001/08/12 03:59:31 kcarnold Exp $
 
  ********************************************************************/
 
@@ -29,27 +29,28 @@
 #endif
 
 #include "ao_interface.h"
+#include "curl_interface.h"
 
 typedef struct ogg123_options_s {
   char *read_file;            /* File to decode */
   char shuffle;               /* Should we shuffle playing? */
-  signed short int verbose;   /* Verbose output if > 0, quiet if < 0 */
-  signed short int quiet;     /* Be quiet (no title) */
+  long int verbose;           /* Verbose output if > 0, quiet if < 0 */
+  long int quiet;             /* Be quiet (no title) */
   double seekpos;             /* Amount to seek by */
   FILE *instream;             /* Stream to read from. */
   char *default_device;       /* default device for playback */
   devices_t *outdevices;      /* Streams to write to. */
-  int buffer_size;            /* Size of the buffer in chunks. */
-  int prebuffer;              /* number of chunks to prebuffer */
+  long outbuffer_size;            /* Size of the buffer in chunks. */
+  float outprebuffer;              /* number of chunks to prebuffer */
   int rate, channels;         /* playback params for opening audio devices */
   int delay;                  /* delay for skip to next song */
   int nth;                    /* Play every nth chunk */
   int ntimes;                 /* Play every chunk n times */
-} ogg123_options_t;           /* Changed in 0.6 to be non-static */
+  InputOpts_t inputOpts;
+} ogg123_options_t;
 
 void usage(void);
-void play_file(ogg123_options_t opt);
-FILE *http_open(char *server, int port, char *path);
+void play_file(ogg123_options_t *opt);
 int open_audio_devices(ogg123_options_t *opt, int rate, int channels);
 void signal_quit (int ignored);
 void ogg123_onexit (int exitcode, void *arg);

No                   revision

No                   revision

1.1.2.1   +392 -0    vorbis-tools/ogg123/Attic/options.c

1.1.2.1   +60 -0     vorbis-tools/ogg123/Attic/options.h

1.1.2.1   +84 -0     vorbis-tools/ogg123/Attic/status.c

1.1.2.1   +40 -0     vorbis-tools/ogg123/Attic/status.h

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