[xiph-cvs] cvs commit: vorbis-tools/ogg123 ogg123.c ogg123rc-example

Kenneth C. Arnold kcarnold at xiph.org
Mon Dec 25 13:24:26 PST 2000



kcarnold    00/12/25 13:24:25

  Modified:    ogg123   ogg123.c ogg123rc-example
  Log:
  Merry Christmas!
  
  Extensive Christmas fixes to ogg123. Just general code cleanup today.
  I don't think I broke anything, and I have tested this pretty extensively.
  Buffered output is coming. HTTP streaming rewrite is coming. Not yet.
  
  Also ogg123rc-example needed a little explanation.

Revision  Changes    Path
1.14      +478 -498  vorbis-tools/ogg123/ogg123.c

Index: ogg123.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- ogg123.c	2000/12/17 20:29:32	1.13
+++ ogg123.c	2000/12/25 21:24:25	1.14
@@ -14,603 +14,583 @@
  *                                                                  *
  ********************************************************************
 
- last mod: $Id: ogg123.c,v 1.13 2000/12/17 20:29:32 giles Exp $
+ last mod: $Id: ogg123.c,v 1.14 2000/12/25 21:24:25 kcarnold Exp $
 
  ********************************************************************/
 
-/* Takes a vorbis bitstream from stdin and writes raw stereo PCM to
-   stdout.  Decodes simple and chained OggVorbis files from beginning
-   to end.  Vorbisfile.a is somewhat more complex than the code below.  */
+/* FIXME : That was a messy message. Fix it. */
 
-#define OGG123_VERSION "0.1"
+#define OGG123_VERSION "0.6 (CVS post-beta3)"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
-#include <sys/socket.h> /* !!! */
+#include <sys/socket.h>
 #include <unistd.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <errno.h>
 #include <math.h>
-#include <getopt.h> /* !!! */
-#include <fcntl.h> /* !!! */
-#include <time.h> /* !!! */
-#include <sys/time.h> /* !!! */
+#include <getopt.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/time.h>
 #include <ogg/ogg.h>
 #include <vorbis/codec.h>
 #include <vorbis/vorbisfile.h>
 #include <ao/ao.h>
 
-char convbuffer[4096];	/* take 8k out of the data segment, not the stack */
+char convbuffer[4096];		/* take 8k out of the data segment, not the stack */
 int convsize = 4096;
 
 /* For facilitating output to multiple devices */
-typedef struct devices_struct 
-{
-  int driver_id;
-  ao_device_t *device;
-  ao_option_t *options;
-  struct devices_struct *next_device;
-} devices;
-
-struct
-{
-  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) */
-  double seekpos;		/* Amount to seek by */
-  FILE *instream;		/* Stream to read from. */
-  devices *outdevices;		/* Streams to write to. */
-}
-param =
-{
-NULL, 0, 0, 0, 0, NULL, NULL};
-
-struct
-{
-  ogg_int64_t c_length;	/* Compressed length */
-  double u_time;	/* Uncompressed time */
-  ogg_int64_t c_pos;	/* Position in the compressed file */
-  double u_pos;		/* Position in the decoded output */
-}
-info =
-{
--1, -1, 0, 0};
+typedef struct devices_s {
+    int driver_id;
+    ao_device_t *device;
+    ao_option_t *options;
+    struct devices_s *next_device;
+} devices_t;
+
+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) */
+    double seekpos;		/* Amount to seek by */
+    FILE *instream;		/* Stream to read from. */
+    devices_t *outdevices;	/* Streams to write to. */
+} ogg123_options_t;		/* Changed in 0.6 to be non-static */
+
+/* There used to be an "info" struct here that served little purpose. */
+
+struct {
+    char *key;			/* includes the '=' for programming convenience */
+    char *formatstr;		/* formatted output */
+} ogg_comment_keys[] = {
+  {"ARTIST=", "Artist: %s\n"},
+  {"ALBUM=", "Album: %s\n"},
+  {"TITLE=", "Title: %s\n"},
+  {"VERSION", "Version: %s\n"},
+  {"ORGANIZATION=", "Organization: %s\n"},
+  {"GENRE=", "Genre: %s\n"},
+  {"DESCRIPTION=", "Description: %s\n"},
+  {"DATE=", "Date: %s\n"},
+  {"LOCATION=", "Location: %s\n"},
+  {"COPYRIGHT=", "Copyright %s\n"},
+  {NULL, NULL}
+};
 
 struct option long_options[] = {
-  {"help", no_argument, 0, 'h'},
-  {"version", no_argument, 0, 'V'},
-  {"device", required_argument, 0, 'd'},
-  {"skip", required_argument, 0, 'k'},
-  {"device-option", required_argument, 0, 'o'},
-  {"verbose", no_argument, 0, 'v'},
-  {"quiet", no_argument, 0, 'q'},
-  {"shuffle", no_argument, 0, 'z'},
-  {0, 0, 0, 0}
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+    {"device", required_argument, 0, 'd'},
+    {"skip", required_argument, 0, 'k'},
+    {"device-option", required_argument, 0, 'o'},
+    {"verbose", no_argument, 0, 'v'},
+    {"quiet", no_argument, 0, 'q'},
+    {"shuffle", no_argument, 0, 'z'},
+    {0, 0, 0, 0}
 };
 
-void play_file (void);		/* This really needs to go in a header file. */
-FILE *http_open (char *server, int port, char *path);
+/* FIXME: XXX: YUCK: fixme. */
+void play_file(ogg123_options_t opt);	/* This really needs to go in a header file. */
+FILE *http_open(char *server, int port, char *path);
 
-void
-append_device (devices ** devices_list, int driver_id, ao_option_t *options)
+devices_t *append_device(devices_t * devices_list, int driver_id,
+			 ao_option_t * options)
 {
-  if (*devices_list != NULL)
-    {
-      while ((*devices_list)->next_device != NULL)
-	{
-	  // Beware of pointers to pointers!
-	  devices_list = &((*devices_list)->next_device);
-	}
-      (*devices_list)->next_device = (devices *) malloc (sizeof (devices));
-      devices_list = &((*devices_list)->next_device);
-    }
-  else
-    {
-      *devices_list = (devices *) malloc (sizeof (devices));
-    }
-  (*devices_list)->driver_id = driver_id;
-  (*devices_list)->options = options;
-  (*devices_list)->next_device = NULL;
-}
+    devices_t *head = devices_list;
 
-void
-free_devices (devices * devices_list)
-{
-  devices temp_device;
-  while (devices_list->next_device)
-    {
-      temp_device = *devices_list;
-      free (devices_list);
-      devices_list = temp_device.next_device;
+    if (devices_list != NULL) {
+	while (devices_list->next_device != NULL)
+	    devices_list = devices_list->next_device;
+	devices_list = devices_list->next_device =
+	    malloc(sizeof(devices_t));
+    } else {
+	head = devices_list = (devices_t *) malloc(sizeof(devices_t));
     }
-  free (devices_list);
+    devices_list->driver_id = driver_id;
+    devices_list->options = options;
+    devices_list->next_device = NULL;
+
+    return head;
 }
 
-void
-devices_write (void *ptr, size_t size, devices *d)
+void devices_write(void *ptr, size_t size, devices_t * d)
 {
-  while (d)
-    {
-      ao_play(d->device, ptr, size);
-      d = d->next_device;
+    while (d != NULL) {
+	ao_play(d->device, ptr, size);
+	d = d->next_device;
     }
 }
 
-void
-usage ()
+void usage()
 {
-  FILE *o;
-  o = stderr;
+    FILE *o;
+    o = stderr;
 
-  fprintf (o, "Ogg123 %s\n", OGG123_VERSION);
-  fprintf (o, " by Kenneth Arnold <kcarnold at yahoo.com> and crew\n\n");
-  fprintf (o, "Usage: ogg123 [<options>] <input file> ...\n\n");
-  fprintf (o, "  -h, --help     this help\n");
-  fprintf (o, "  -V, --version  display Ogg123 version\n");
-  fprintf (o, "  -d, --device=d uses 'd' as an output device)\n");
-  fprintf (o, "      Possible devices are (some may not be compiled):\n");
-  fprintf (o, "      null (output nothing), oss (for Linux and *BSD),\n");
-  fprintf (o, "      irix, solaris, wav (write to a .WAV file)\n");
-  fprintf (o, "  -k n, --skip n  Skip the first 'n' seconds\n");
-  fprintf (o, 
-           "  -o, --device-option=k:v passes special option k with value\n");
-  fprintf (o, 
-           "      v to previously specified device (with -d).  See\n");
-  fprintf (o, 
-           "      man page for more info.\n");
-
-  fprintf (o,
-	   "  -v, --verbose  display progress and other useful stuff (not yet)\n");
-  fprintf (o, "  -q, --quiet    don't display anything (no title)\n");
-  fprintf (o, "  -z, --shuffle  shuffle play\n");
+    fprintf(o,
+	    "Ogg123 " OGG123_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 (some may not be compiled):\n"
+	    "      null (output nothing), oss (for Linux and *BSD),\n"
+	    "      irix, solaris, wav (write to a .WAV file)\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"
+	    "  -v, --verbose  display progress and other useful stuff\n"
+	    "  -q, --quiet    don't display anything (no title)\n"
+	    "  -z, --shuffle  shuffle play\n");
 }
 
-int add_option(ao_option_t **op_h, const char *optstring)
+int add_option(ao_option_t ** op_h, const char *optstring)
 {
-	char *key, *value;
-	int  result;
+    char *key, *value;
+    int result;
 
-	key = strdup(optstring);
-	if (key == NULL) return 0;
+    key = strdup(optstring);
+    if (key == NULL)
+	return 0;
 
-	value = strchr(key, ':');
-	if (value == NULL) {
-		free(key);
-		return 0;
-	}
-	
-	/* split by replacing the separator with a null */
-	*value++ = '\0';
-
-	result = ao_append_option(op_h, key, value);
-	free (key);
-	
-	return (result);
+    value = strchr(key, ':');
+    if (value == NULL) {
+	free(key);
+	return 0;
+    }
+
+    /* split by replacing the separator with a null */
+    *value++ = '\0';
+
+    result = ao_append_option(op_h, key, value);
+    free(key);
+
+    return (result);
 }
 
 int get_default_device(void)
 {
-	FILE *fp;
-	char filename[NAME_MAX];
-	char line[100];
-	char *device = NULL;
-	int i;
+    FILE *fp;
+    char filename[NAME_MAX];
+    char line[100];
+    char *device = NULL;
+    char *homedir = getenv("HOME");
+    int i;
+
+    /* Maybe I'm being extremely paranoid, but if ogg123 is ever suid
+       root (to access audio devices), this is a possible buffer overflow. */
+    if (homedir == NULL || strlen(homedir) >= NAME_MAX - 10)
+	return -1;
 
-	strncpy(filename, getenv("HOME"), NAME_MAX);
-	strcat(filename, "/.ogg123rc");
+    strncpy(filename, homedir, NAME_MAX);
+    strcat(filename, "/.ogg123rc");
 
-	fp = fopen(filename, "r");
-	if (fp) {
-		if (fgets(line, 100, fp)) {
-			if (strncmp(line, "default_device=", 15) == 0) {
-				device = &line[15];
-				for (i = 0; i < strlen(device); i++)
-					if (device[i] == '\n' || device[i] == '\r')
-						device[i] = 0;
-			}
-		}
-		fclose(fp);
-	}
 
-	if (device) return ao_get_driver_id(device);
-
-	return -1;
+    /* This is a very simplistic parser. If more options are ever added,
+       it will need a serious overhaul. */
+    fp = fopen(filename, "r");
+    if (fp) {
+      if (getline(line, 100, fp)) {
+	if (strncmp(line, "default_device=", 15) == 0) {
+	  device = &line[15];
+	  for (i = 0; i < strlen(device); i++)
+	    if (device[i] == '\n' || device[i] == '\r')
+	      device[i] = 0;
+	}
+      }
+      fclose(fp);
+    }
+    
+    if (device)
+      return ao_get_driver_id(device);
+    
+    return -1;
 }
 
-int
-main (int argc, char **argv)
+int main(int argc, char **argv)
 {
-  /* Parse command line */
-
-  int ret;
-  int option_index = 1;
-  ao_option_t *temp_options = NULL;
-  int temp_driver_id = -1;
-  devices *current;
-  int bits, rate, channels;
-
-  ao_initialize();
-
-  temp_driver_id = get_default_device();
-
-  while (-1 != (ret = getopt_long (argc, argv, "d:hqk:o:vV:z",
-				   long_options, &option_index)))
-    {
-      switch (ret)
-	{
+    ogg123_options_t opt;
+    int ret;
+    int option_index = 1;
+    ao_option_t *temp_options = NULL;
+    int temp_driver_id = -1;
+    devices_t *current;
+    int bits, rate, channels;
+
+    opt.read_file = NULL;
+    opt.shuffle = 0;
+    opt.verbose = 0;
+    opt.quiet = 0;
+    opt.seekpos = 0;
+    opt.instream = NULL;
+    opt.outdevices = NULL;
+
+    ao_initialize();
+
+    temp_driver_id = get_default_device();
+
+    while (-1 != (ret = getopt_long(argc, argv, "d:hqk:o:vV:z",
+				    long_options, &option_index))) {
+	switch (ret) {
         case 0:
-	  fprintf (stderr,
-		   "Internal error: long option given when none expected.\n");
-	  exit (1);
+	    fprintf(stderr,
+		    "Internal error: long option given when none expected.\n");
+	    exit(1);
         case 'd':
-	  /* Need to store previous device before gathering options for
-	     this device */
-	  if (temp_driver_id != -1)
-	    {
-	      append_device(&param.outdevices, temp_driver_id, temp_options);
-	      temp_options = NULL;
+	    /* Need to store previous device before gathering options for
+	       this device */
+	    if (temp_driver_id != -1) {
+		opt.outdevices =
+		    append_device(opt.outdevices, temp_driver_id,
+				  temp_options);
+		temp_options = NULL;
             }
-	  temp_driver_id = ao_get_driver_id(optarg);
-	  if (temp_driver_id < 0)
-	    {
-	      fprintf(stderr, "No such device %s.\n", optarg);
-	      exit(1);
+	    temp_driver_id = ao_get_driver_id(optarg);
+	    if (temp_driver_id < 0) {
+		fprintf(stderr, "No such device %s.\n", optarg);
+		exit(1);
             }
-	  break;
+	    break;
         case 'k':
-	  param.seekpos = atof (optarg);
-	  break;
+	    opt.seekpos = atof(optarg);
+	    break;
         case 'o':
-	  if (optarg && !add_option(&temp_options, optarg))
-	    {
-	      fprintf(stderr, "Incorrect option format: %s.\n", optarg);
-	      exit(1);
+	    if (optarg && !add_option(&temp_options, optarg)) {
+		fprintf(stderr, "Incorrect option format: %s.\n", optarg);
+		exit(1);
             }
-	  break;
+	    break;
         case 'h':
-	  usage ();
-	  exit (0);
+	    usage();
+	    exit(0);
         case 'q':
-	  param.quiet++;
-	  break;
+	    opt.quiet++;
+	    break;
         case 'v':
-	  param.verbose++;
-	  break;
+	    opt.verbose++;
+	    break;
         case 'V':
-	  fprintf (stderr, "Ogg123 %s\n", OGG123_VERSION);
-	  exit (0);
+	    fprintf(stderr, "Ogg123 %s\n", OGG123_VERSION);
+	    exit(0);
         case 'z':
-	  param.shuffle = 1;
-	  break;
+	    opt.shuffle = 1;
+	    break;
         case '?':
-	  break;
+	    break;
         default:
-	  usage ();
-	  exit (1);
+	    usage();
+	    exit(1);
         }
     }
-  
-  /* Add last device to device list or use the default device */
-  if (temp_driver_id < 0)
-    {
-      temp_driver_id = ao_get_driver_id(NULL);
-      if (temp_driver_id < 0)
-	{
-	  fprintf(stderr, "Internal Error: Could not load default driver.\n");
-	  exit(1);
+
+    /* Add last device to device list or use the default device */
+    if (temp_driver_id < 0) {
+	temp_driver_id = ao_get_driver_id(NULL);
+	if (temp_driver_id < 0) {
+	    fprintf(stderr,
+		    "Could not load default driver and no ~/.ogg123_rc found. Exiting.\n");
+	    exit(1);
         }
     }
 
-  append_device(&param.outdevices, temp_driver_id, temp_options);
-  
-  if (optind == argc)
-    {
-      fprintf (stderr,
-	       "Please specify a file to decode on the command line.\n");
-      exit (1);
-    }
-
-  /* Open all of the devices */
-  bits = 16;
-  rate = 44100;
-  channels = 2;
-  current = param.outdevices;
-
-  if (param.quiet < 1)
-	  fprintf(stderr, "Opening devices...\n");
-
-  while (current != NULL) {
-    ao_info_t *info = ao_get_driver_info(current->driver_id);
-
-    if (param.quiet < 1) {
-    	fprintf(stderr, "Device:   %s\n", info->name);
-    	fprintf(stderr, "Author:   %s\n", info->author);
-    	fprintf(stderr, "Comments: %s\n", info->comment);
-    }
-    
-    current->device = ao_open(current->driver_id,bits,rate,channels,
-			     current->options);
-    if (current->device == NULL)
-      {
-	fprintf(stderr, "Error opening device.\n");
+    opt.outdevices =
+	append_device(opt.outdevices, temp_driver_id, temp_options);
+
+    if (optind == argc) {
+	usage();
         exit(1);
-      }
-    if (param.quiet < 1)
-    	fprintf(stderr, "\n"); // Gotta keep 'em separated ...
- 
-    current = current->next_device;
-  }
-
-  if (param.shuffle)
-    {
-      int i;
-      int nb = argc - optind;
-      int *p = alloca(sizeof(int) * nb);
-      for (i = 0; i < nb; i++) p[i] = i;
-
-      srand (time (NULL));
-      for (i = 1; i < nb; i++) 
-	{
-	  int j = i * ((float) rand() / RAND_MAX);
-	  int temp = p[j]; p[j] = p[i]; p[i] = temp;
-	}
-      for (i = 0; i < nb; i++) 
-	{
-	  param.read_file = argv[p[i]+optind];
-	  play_file ();
-	}
-    }
-  else
-    {
-      while (optind < argc)
-	{
-	  param.read_file = argv[optind];
-	  play_file ();
-	  optind++;
-	}
     }
 
-  current = param.outdevices;
-
-  while(current != NULL)
-  {
-	  ao_close(current->device);
-	  current = current->next_device;
-  }
+    /* Open all of the devices */
 
-  ao_shutdown();
+    /* FIXME: OggVorbis files aren't all 16 bit 44.1k stereo. */
+    /* Heck, they might not even be Vorbis :) PCM-Ogg? */
+    bits = 16;
+    rate = 44100;
+    channels = 2;
+    current = opt.outdevices;
 
-  return (0);
-}
+    if (opt.verbose > 0)
+	fprintf(stderr, "Opening devices...\n");
 
-void play_file(void)
-{
-	OggVorbis_File vf;
-	int current_section = -1, eof = 0, eos = 0, ret;
-	int old_section = -1;
-	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 = param.seekpos;
-
-  if (strcmp (param.read_file, "-"))	/* input file not stdin */
-    {
-      if (!strncmp (param.read_file, "http://", 7))
-	{
-	  /* Stream down over http */
-	  char *temp = NULL, *server = NULL, *port = NULL, *path = NULL;
-	  int index;
-	  long iport;
-	  
-	  temp = param.read_file + 7;
-	  for (index = 0; temp[index] != '/' && temp[index] != ':'; index++);
-	  server = (char *) malloc (index + 1);
-	  strncpy (server, temp, index);
-	  server[index] = '\0';
+    while (current != NULL) {
+	ao_info_t *info = ao_get_driver_info(current->driver_id);
 
-	  /* 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);
+	if (opt.verbose > 0) {
+	    fprintf(stderr, "Device:   %s\n", info->name);
+	    fprintf(stderr, "Author:   %s\n", info->author);
+	    fprintf(stderr, "Comments: %s\n", info->comment);
+	}
+
+	current->device = ao_open(current->driver_id, bits, rate, channels,
+				  current->options);
+	if (current->device == NULL) {
+	    fprintf(stderr, "Error opening device.\n");
+	    exit(1);
+	}
+	if (opt.quiet < 1)
+	    fprintf(stderr, "\n");	// Gotta keep 'em separated ...
+
+	current = current->next_device;
+    }
+
+    if (opt.shuffle) {
+	/* Messy code that I didn't write -ken */
+	int i;
+	int nb = argc - optind;
+	int *p = alloca(sizeof(int) * nb);
+	for (i = 0; i < nb; i++)
+	    p[i] = i;
+
+	srand(time(NULL));
+	for (i = 1; i < nb; i++) {
+	    int j = i * ((float) rand() / RAND_MAX);
+	    int temp = p[j];
+	    p[j] = p[i];
+	    p[i] = temp;
+	}
+	for (i = 0; i < nb; i++) {
+	    opt.read_file = argv[p[i] + optind];
+	    play_file(opt);
+	}
+    } else {
+	while (optind < argc) {
+	    opt.read_file = argv[optind];
+	    play_file(opt);
+	    optind++;
+	}
+    }
+
+    while (opt.outdevices != NULL) {
+	ao_close(opt.outdevices->device);
+	current = opt.outdevices->next_device;
+	free(opt.outdevices);
+	opt.outdevices = current;
+    }
+
+    ao_shutdown();
+
+    return (0);
+}
+
+void play_file(ogg123_options_t opt)
+{
+    /* Oh my gosh this is disgusting. Big cleanups here will include an
+       almost complete rewrite of the hacked-out HTTP streaming, a shift
+       to using callbacks for the vorbisfile input, and a (mostly Unix-specific)
+       buffer. Probably use shm. */
+
+    OggVorbis_File vf;
+    int current_section = -1, eof = 0, eos = 0, ret;
+    int old_section = -1;
+    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;
+
+    /* Junk left over from the failed info struct */
+    double u_time, u_pos;
+
+    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);
             }
-	  else iport = 80;
-	  
-	  path = strdup (temp + index);
+	    /* 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);
 
-	  if ((param.instream = http_open (server, iport, path)) == NULL)
+	    /* Dump headers */
             {
-	      fprintf (stderr, "Error while connecting to server!\n");
-	      exit (1);
+		char last = 0, in = 0;
+		int eol = 0;
+
+		/* Need to 'quiet' this header dump */
+		fprintf(stderr, "HTTP Headers:\n");
+		for (;;) {
+		    last = in;
+		    in = getc(opt.instream);
+		    putc(in, stderr);
+		    if (last == 13 && in == 10) {
+			if (eol)
+			    break;
+			eol = 1;
+		    } else if (in != 10 && in != 13)
+			eol = 0;
+		}
             }
-	  /* Send HTTP header */
-	  fprintf (param.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);
-
-	  /* Dump headers */
-	  {
-	    char last = 0, in = 0;
-	    int eol = 0;
-		
-	    /* Need to 'quiet' this header dump */
-	    fprintf (stderr, "HTTP Headers:\n");
-	    for (;;)
-	      {
-		last = in;
-		in = getc (param.instream);
-		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
-	{
-	  if (param.quiet < 1)
-	  	fprintf (stderr, "Playing from file %s.\n", param.read_file);
-	  /* Open the file. */
-	  if ((param.instream = fopen (param.read_file, "rb")) == NULL)
-	    {
-	      fprintf (stderr, "Error opening input file.\n");
-	      exit (1);
+	    free(server);
+	    free(path);
+	} else {
+	    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) {
+		fprintf(stderr, "Error opening input file.\n");
+		exit(1);
             }
         }
+    } else {
+	if (opt.quiet < 1)
+	    fprintf(stderr, "Playing from standard input.\n");
+	opt.instream = stdin;
     }
-  else
-    {
-      if (param.quiet < 1)
-	      fprintf (stderr, "Playing from standard input.\n");
-      param.instream = stdin;
-    }
-
-	if ((ov_open(param.instream, &vf, NULL, 0)) < 0) {
-		fprintf(stderr, "E: input not an Ogg Vorbis audio stream.\n");
-		return;
-	}
-  
-	/* Throw the comments plus a few lines about the bitstream we're
-	** decoding */
 
-	while (!eof) {
-		int i;
-		vorbis_comment *vc = ov_comment(&vf, -1);
-		vorbis_info *vi = ov_info(&vf, -1);
+    if ((ov_open(opt.instream, &vf, NULL, 0)) < 0) {
+	fprintf(stderr, "E: input not an Ogg Vorbis audio stream.\n");
+	return;
+    }
 
-		if (param.quiet < 1) {
-			for (i = 0; i < vc->comments; i++) {
-				char *cc = vc->user_comments[i]; /* current comment */
-				if (!strncasecmp ("ARTIST=", cc, 7))
-					fprintf(stderr, "Artist: %s\n", cc + 7);
-				else if (!strncasecmp("ALBUM=", cc, 6))
-					fprintf(stderr, "Album: %s\n", cc + 6);
-				else if (!strncasecmp("TITLE=", cc, 6))
-					fprintf(stderr, "Title: %s\n", cc + 6);
-				else if (!strncasecmp("VERSION=", cc, 8))
-					fprintf(stderr, "Version: %s\n", cc + 8);
-				else if (!strncasecmp("ORGANIZATION=", cc, 13))
-					fprintf(stderr, "Organization: %s\n", cc + 13);
-				else if (!strncasecmp("GENRE=", cc, 6))
-					fprintf(stderr, "Genre: %s\n", cc + 6);
-				else if (!strncasecmp("DESCRIPTION=", cc, 12))
-					fprintf(stderr, "Description: %s\n", cc + 12);
-				else if (!strncasecmp("DATE=", cc, 5))
-					fprintf(stderr, "Date: %s\n", cc + 5);
-				else if (!strncasecmp("LOCATION=", cc, 9))
-					fprintf(stderr, "Location: %s\n", cc + 9);
-				else if (!strncasecmp("COPYRIGHT=", cc, 10))
-					fprintf(stderr, "Copyright: %s\n", cc + 10);
-				else
-					fprintf(stderr, "Unrecognized comment: %s\n", cc);
-			}
-    
-		fprintf(stderr, "\nBitstream is %d channel, %ldHz\n", vi->channels, vi->rate);
-		fprintf(stderr, "Encoded by: %s\n\n", vc->vendor);
-		}
+    /* Throw the comments plus a few lines about the bitstream we're
+       ** decoding */
 
-		if (param.verbose > 0) {
-			/* Seconds with double precision */
-			info.u_time = ov_time_total(&vf, -1);
-			t_min = (long)info.u_time / (long)60;
-			t_sec = info.u_time - 60 * t_min;
-		}
+    while (!eof) {
+	int i;
+	vorbis_comment *vc = ov_comment(&vf, -1);
+	vorbis_info *vi = ov_info(&vf, -1);
+
+	if (opt.quiet < 1) {
+	    for (i = 0; i < vc->comments; i++) {
+		char *cc = vc->user_comments[i];	/* current comment */
+		int i;
+
+		for (i = 0; ogg_comment_keys[i].key != NULL; i++)
+		    if (!strncmp
+			(ogg_comment_keys[i].key, cc,
+			 strlen(ogg_comment_keys[i].key))) {
+			fprintf(stderr, ogg_comment_keys[i].formatstr,
+				cc + strlen(ogg_comment_keys[i].key));
+			break;
+		    }
+		if (ogg_comment_keys[i].key == NULL)
+		    fprintf(stderr, "Unrecognized comment: '%s'\n");
+	    }
 
-		if ((realseekpos > ov_time_total (&vf, -1)) || (realseekpos < 0))
-	         /* If we're out of range set it to right before the end. If we set it
-        	  * right to the end when we seek it will go to the beginning of the sond */
-			realseekpos = ov_time_total (&vf, -1) - 0.01;
- 
-		if (realseekpos > 0)
-			ov_time_seek (&vf, realseekpos);
-
-		eos = 0;
-		while (!eos) {
-			old_section = current_section;
-			ret = ov_read(&vf, convbuffer, sizeof (convbuffer), is_big_endian, 2, 1, &current_section);
-			if (ret == 0) {
-				/* End of file */
-				eof = eos = 1;
-			} else if (ret < 0) {
-				/* Stream error */
-				fprintf(stderr, "W: Stream error\n");
-			} else {
-				/* less bytes than we asked for */
-				/* did we enter a new logical bitstream */
-				if (old_section != current_section && old_section != -1)
-					eos = 1;
-
-				devices_write(convbuffer, ret, param.outdevices);
-				if (param.verbose > 0) {
-					info.u_pos = ov_time_tell(&vf);
-					c_min = (long)info.u_pos / (long)60;
-					c_sec = info.u_pos - 60 * c_min;
-					r_min = (long)(info.u_time - info.u_pos) / (long)60;
-					r_sec = (info.u_time - info.u_pos) - 60 * r_min;
-					fprintf (stderr, "\rTime: %02li:%05.2f [%02li:%05.2f] of %02li:%05.2f, Bitrate: %.1f   \r", c_min, c_sec, r_min, r_sec, t_min, t_sec, (float)ov_bitrate_instant(&vf) / 1000.0F);
-				}
-			}
+	    fprintf(stderr, "\nBitstream is %d channel, %ldHz\n",
+		    vi->channels, vi->rate);
+	    fprintf(stderr, "Encoded by: %s\n\n", vc->vendor);
+	}
+
+	if (opt.verbose > 0) {
+	    /* Seconds with double precision */
+	    u_time = ov_time_total(&vf, -1);
+	    t_min = (long) u_time / (long) 60;
+	    t_sec = u_time - 60 * t_min;
+	}
+
+	if ((realseekpos > ov_time_total(&vf, -1)) || (realseekpos < 0))
+	    /* If we're out of range set it to right before the end. If we set it
+	     * right to the end when we seek it will go to the beginning of the sond */
+	    realseekpos = ov_time_total(&vf, -1) - 0.01;
+
+	if (realseekpos > 0)
+	    ov_time_seek(&vf, realseekpos);
+
+	eos = 0;
+	while (!eos) {
+	    old_section = current_section;
+	    ret =
+		ov_read(&vf, convbuffer, sizeof(convbuffer), is_big_endian,
+			2, 1, &current_section);
+	    if (ret == 0) {
+		/* End of file */
+		eof = eos = 1;
+	    } else if (ret < 0) {
+		/* Stream error */
+		fprintf(stderr, "W: Stream error\n");
+	    } else {
+		/* less bytes than we asked for */
+		/* did we enter a new logical bitstream */
+		if (old_section != current_section && old_section != -1)
+		    eos = 1;
+
+		devices_write(convbuffer, ret, opt.outdevices);
+		if (opt.verbose > 0) {
+		    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;
+		    fprintf(stderr,
+			    "\rTime: %02li:%05.2f [%02li:%05.2f] of %02li:%05.2f, Bitrate: %.1f   \r",
+			    c_min, c_sec, r_min, r_sec, t_min, t_sec,
+			    (float) ov_bitrate_instant(&vf) / 1000.0F);
                 }
+	    }
         }
+    }
+
+    ov_clear(&vf);
 
-	ov_clear(&vf);
-      
-	if (param.quiet < 1)
-		fprintf (stderr, "\nDone.\n");
+    if (opt.quiet < 1)
+	fprintf(stderr, "\nDone.\n");
 }
 
 int get_tcp_socket(void)
 {
-	return socket(AF_INET, SOCK_STREAM, 0);
+    return socket(AF_INET, SOCK_STREAM, 0);
 }
 
-FILE *http_open (char *server, int port, char *path)
+FILE *http_open(char *server, int port, char *path)
 {
-  int sockfd = get_tcp_socket ();
-  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;
+    int sockfd = get_tcp_socket();
+    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;
     }
-  return fdopen (sockfd, "r+b");
-}  
+
+    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");
+}

1.2       +2 -0      vorbis-tools/ogg123/ogg123rc-example

Index: ogg123rc-example
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123rc-example,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ogg123rc-example	2000/10/31 01:06:22	1.1
+++ ogg123rc-example	2000/12/25 21:24:25	1.2
@@ -1 +1,3 @@
+# Copy this to ~/.ogg123rc and edit as necessary. The current
+# parser cannot handle comments, so remove these lines also.
 default_device=oss

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