Index: roarclients/Makefile
===================================================================
--- roarclients/Makefile	(revision 83)
+++ roarclients/Makefile	(revision 111)
@@ -1,3 +1,3 @@
-TARGETS=roarcat roarcatad roarcat2sock roarctl roarmon roarsockconnect roartypes
+TARGETS=roarcat roarcatad roarcat2sock roarctl roarmon roarsockconnect roartypes roarvorbis
 
 DEFINES        = -DDEBUG
@@ -19,2 +19,4 @@
 roarsockconnect: roarsockconnect.o
 roartypes: roartypes.o
+roarvorbis: roarvorbis.o
+	${CC} ${LDFLAGS} -o roarvorbis roarvorbis.o -lvorbisfile
Index: roarclients/roarvorbis.c
===================================================================
--- roarclients/roarvorbis.c	(revision 111)
+++ roarclients/roarvorbis.c	(revision 111)
@@ -0,0 +1,153 @@
+//roarvorbis.c:
+
+#include <roaraudio.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <vorbis/codec.h>
+#include <vorbis/vorbisfile.h>
+
+#ifdef _WIN32
+#include <io.h>
+#include <fcntl.h>
+#endif
+
+#define BUFSIZE 1024
+
+void usage (void) {
+ printf("roarvorbis [OPTIONS]... FILE\n");
+
+ printf("\nOptions:\n\n");
+
+ printf("  --server SERVER    - Set server hostname\n"
+        "  --help             - Show this help\n"
+       );
+
+}
+
+int main (int argc, char * argv[]) {
+ int    rate     = 44100;
+ int    bits     = 16;
+ int    channels = 2;
+ int    codec    = ROAR_CODEC_DEFAULT;
+ char * server   = NULL;
+ char * file     = NULL;
+ char * k;
+ int    i;
+ FILE * in;
+ struct roar_connection con;
+ struct roar_stream     s;
+ OggVorbis_File vf;
+ int eof=0;
+ int current_section;
+ char pcmout[4096];
+
+
+ for (i = 1; i < argc; i++) {
+  k = argv[i];
+
+  if ( strcmp(k, "--server") == 0 ) {
+   server = argv[++i];
+  } else if ( strcmp(k, "--help") == 0 ) {
+   usage();
+   return 0;
+  } else if ( file == NULL ) {
+   file = k;
+  } else {
+   fprintf(stderr, "Error: unknown argument: %s\n", k);
+   usage();
+   return 1;
+  }
+ }
+
+ if ( roar_simple_connect(&con, server, "roarcatad") == -1 ) {
+  ROAR_DBG("roar_simple_play(*): roar_simple_connect() faild!");
+  return -1;
+ }
+
+ if ( roar_stream_new(&s, rate, channels, bits, codec) == -1 ) {
+  roar_disconnect(&con);
+  return -1;
+ }
+
+ if ( roar_stream_connect(&con, &s, ROAR_DIR_PLAY) == -1 ) {
+  roar_disconnect(&con);
+  return -1;
+ }
+
+ if ( (in = fopen(file, "rb")) == NULL ) {
+  roar_disconnect(&con);
+  return -1;
+ }
+
+#ifdef _WIN32
+  _setmode(_fileno(in), _O_BINARY);
+#endif
+
+ if(ov_open(in, &vf, NULL, 0) < 0) {
+  fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n");
+  roar_disconnect(&con);
+  return -1;
+ }
+
+ {
+  char **ptr=ov_comment(&vf,-1)->user_comments;
+  char key[80], value[80];
+  int j, h = 0;
+  vorbis_info *vi=ov_info(&vf,-1);
+  struct roar_meta   meta;
+
+  meta.value = value;
+  meta.key[0] = 0;
+
+  while(*ptr){
+    fprintf(stderr,"%s\n",*ptr);
+
+    for (j = 0; (*ptr)[j] != 0 && (*ptr)[j] != '='; j++)
+     key[j] = (*ptr)[j];
+     key[j] = 0;
+
+    for (j++, h = 0; (*ptr)[j] != 0 && (*ptr)[j] != '='; j++)
+     value[h++] = (*ptr)[j];
+     value[h]   = 0;
+
+    meta.type = roar_meta_inttype(key);
+    if ( meta.type != -1 )
+     roar_stream_meta_set(&con, &s, ROAR_META_MODE_SET, &meta);
+
+    ++ptr;
+  }
+  fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate);
+  fprintf(stderr,"Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor);
+ }
+
+ if ( roar_stream_exec(&con, &s) == -1 ) {
+  roar_disconnect(&con);
+  return -1;
+ }
+  
+ while(!eof){
+  long ret=ov_read(&vf,pcmout,sizeof(pcmout),0,2,1,&current_section);
+  if (ret == 0) {
+   /* EOF */
+   eof=1;
+  } else if (ret < 0) {
+   /* error in the stream.  Not a problem, just reporting it in
+      case we (the app) cares.  In this case, we don't. */
+  } else {
+     /* we don't bother dealing with sample rate changes, etc, but
+        you'll have to */
+    write(con.fh, pcmout, ret);
+  }
+ }
+
+  ov_clear(&vf);
+
+// fclose(in);
+ close(con.fh);
+
+ return 0;
+}
+
+//ll
