[xiph-commits] r12217 - trunk/vorbis-tools/ogg123

conrad at svn.xiph.org conrad at svn.xiph.org
Sat Dec 16 16:32:18 PST 2006


Author: conrad
Date: 2006-12-16 16:32:14 -0800 (Sat, 16 Dec 2006)
New Revision: 12217

Added:
   trunk/vorbis-tools/ogg123/remote.c
   trunk/vorbis-tools/ogg123/remote.h
Log:
add remote.[ch] (forgotten on last commit ...)


Added: trunk/vorbis-tools/ogg123/remote.c
===================================================================
--- trunk/vorbis-tools/ogg123/remote.c	2006-12-16 23:45:16 UTC (rev 12216)
+++ trunk/vorbis-tools/ogg123/remote.c	2006-12-17 00:32:14 UTC (rev 12217)
@@ -0,0 +1,404 @@
+/* remote.c by Richard van Paasen <rvpaasen at dds.nl> */
+
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
+ * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
+ * PLEASE READ THESE TERMS BEFORE DISTRIBUTING.                     *
+ *                                                                  *
+ * THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2001                *
+ * by Kenneth C. Arnold <ogg at arnoldnet.net> AND OTHER CONTRIBUTORS  *
+ * http://www.xiph.org/                                             *
+ *                                                                  *
+ ********************************************************************
+
+ last mod: $Id: remote.c,v 1.4 2002/11/22 22:52:01 rvpaasen Exp $
+
+ ********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+#include "ogg123.h"
+#include "format.h"
+
+/* Maximum size of the input buffer */
+#define MAXBUF 1024
+/* Undefine logfile if you don't want it */
+//#define LOGFILE "/tmp/ogg123.log"
+
+/* The play function in ogg123.c */
+extern void play (char *source_string);
+extern ogg123_options_t options;
+extern void set_seek_opt(ogg123_options_t *ogg123_opts, char *buf);
+
+/* Status */
+typedef enum { PLAY, STOP, PAUSE, NEXT, QUIT} Status;
+static Status status = STOP;
+
+/* Threading is introduced to reduce the
+   amount of processor time that ogg123
+   will take if it is in idle state */
+
+/* Thread control locks */
+static pthread_mutex_t main_lock;
+static sem_t sem_command;
+static sem_t sem_processed;
+static pthread_mutex_t output_lock;
+
+#ifdef LOGFILE
+void send_log(const char* fmt, ...) {
+
+  FILE* fp;
+  va_list ap;
+  pthread_mutex_lock (&output_lock);
+  fp=fopen(LOGFILE,"a");
+  va_start(ap, fmt);
+  vfprintf(fp, fmt, ap);
+  va_end(ap);
+  fprintf(fp, "\n");
+  fclose(fp);
+  pthread_mutex_unlock (&output_lock);
+  return;
+}
+#else
+  #define send_log(...)
+#endif
+
+static void send_msg(const char* fmt, ...) {
+
+  va_list ap;
+  pthread_mutex_lock (&output_lock);
+  fprintf(stdout, "@");
+  va_start(ap, fmt);
+  vfprintf(stdout, fmt, ap);
+  va_end(ap);
+  fprintf(stdout, "\n");
+  pthread_mutex_unlock (&output_lock);
+  return;
+}
+
+static void send_err(const char* fmt, ...) {
+  va_list ap;
+  pthread_mutex_lock (&output_lock);
+  fprintf(stderr, "@");
+  va_start(ap, fmt);
+  vfprintf(stderr, fmt, ap);
+  va_end(ap);
+  fprintf(stderr, "\n");
+  pthread_mutex_unlock (&output_lock);
+  return;
+}
+
+static Status getstatus() {
+
+  return status;
+}
+
+static void setstatus(Status s) {
+
+  status = s;
+}
+
+static void invertpause() {
+
+  if (status==PLAY) {
+    status = PAUSE;
+  }
+  else if (status==PAUSE) {
+    status = PLAY;
+  }
+  return;
+}
+
+static void * remotethread(void * arg) {
+
+  int done = 0;
+  int error = 0;
+  int ignore = 0;
+  char buf[MAXBUF+1];
+  char *b;
+  
+  buf[MAXBUF]=0;
+
+  while(!done) {
+    /* Read a line */
+    buf[0] = 0;
+    send_log("Waiting for input: ...");
+
+    while (fgets(buf, MAXBUF, stdin) == NULL);
+    buf[strlen(buf)-1] = 0;
+
+    /* Lock on */
+    pthread_mutex_lock (&main_lock);
+
+    send_log("Input: %s", buf);
+    error = 0;
+
+    if (!strncasecmp(buf,"l",1)) {
+	/* prepare to load */
+      if ((b=strchr(buf,' ')) != NULL) {
+        /* Prepare to load a new song */
+        strcpy((char*)arg, b+1);
+        setstatus(NEXT);
+      } 
+      else {
+        /* Invalid load command */
+        error = 1;
+      }
+    }
+    else
+    if (!strncasecmp(buf,"p",1)) {
+      /* Prepare to (un)pause */
+      invertpause();
+    }
+	else
+    if (!strncasecmp(buf,"j",1)) {
+      /* Prepare to seek */
+      if ((b=strchr(buf,' ')) != NULL) {
+        set_seek_opt(&options, b+1);
+	  }
+      ignore = 1;
+    }
+    else
+    if (!strncasecmp(buf,"s",1)) {
+      /* Prepare to stop */
+      setstatus(STOP);
+    }
+	else
+    if (!strncasecmp(buf,"r",1)) {
+      /* Prepare to reload */
+      setstatus(NEXT);
+    }
+    else
+    if (!strncasecmp(buf,"h",1)) {
+      /* Send help */
+	  send_msg("H +----------------------------------------------------+");
+	  send_msg("H | Ogg123 remote interface                            |");
+	  send_msg("H |----------------------------------------------------|");
+	  send_msg("H | Load <file>     -  load a file and starts playing  |");
+	  send_msg("H | Pause           -  pause or unpause playing        |");
+	  send_msg("H | Jump [+|-]<f>   -  jump <f> seconds forth or back  |");
+	  send_msg("H | Stop            -  stop playing                    |");
+	  send_msg("H | Reload          -  reload last song                |");
+	  send_msg("H | Quit            -  quit ogg123                     |");
+	  send_msg("H |----------------------------------------------------|");
+	  send_msg("H | refer to README.remote for documentation           |");
+	  send_msg("H +----------------------------------------------------+");
+	  ignore = 1;
+    }
+    else
+    if (!strncasecmp(buf,"q",1)) {
+      /* Prepare to quit */
+      setstatus(QUIT);
+      done = 1;
+    }
+    else {
+      /* Unknown input received */
+      error = 1;
+    }
+
+    if (ignore) {
+      /* Unlock */
+      pthread_mutex_unlock (&main_lock);
+      ignore = 0;
+    } else {
+      if (error) {
+    	/* Send the error and unlock */
+    	send_err("E Unknown command '%s'", buf);
+    	send_log("Unknown command '%s'", buf);
+		/* Unlock */
+    	pthread_mutex_unlock (&main_lock);
+      } 
+      else {
+    	/* Signal the main thread */
+    	sem_post(&sem_command);
+    	/* Unlock */
+    	pthread_mutex_unlock (&main_lock);
+    	/* Wait until the change has been noticed */
+    	sem_wait(&sem_processed);
+      }
+    }
+  }
+
+  return NULL;
+}
+
+void remote_mainloop(void) {
+
+  int r;
+  pthread_t th;
+  Status s;
+  char fname[MAXBUF+1];
+
+  /* Need to output line by line! */
+  setlinebuf(stdout);
+
+  /* Send a greeting */
+  send_msg("R ogg123 from " PACKAGE " " VERSION);
+
+  /* Initialize the thread controlling variables */
+  pthread_mutex_init(&main_lock, NULL);
+  sem_init(&sem_command, 0, 0);
+  sem_init(&sem_processed, 0, 0);
+
+  /* Start the thread */
+  r = pthread_create(&th, NULL, remotethread, (void*)fname);
+  if (r != 0) {
+    send_err("E Could not create a thread (code %d)", r);
+    return;
+  }
+
+  send_log("Start");
+
+  /* The thread may already have processed some input,
+     get the current status
+   */
+  pthread_mutex_lock(&main_lock);
+  s = getstatus();
+  pthread_mutex_unlock(&main_lock);
+
+  while (s != QUIT) {
+
+    /* wait for a new command */
+    if (s != NEXT) {
+
+      /* Wait until a new status is available,
+         This puts the main tread asleep and
+         saves resources
+       */
+       
+      sem_wait(&sem_command);
+
+      pthread_mutex_lock(&main_lock);
+      s = getstatus();
+      pthread_mutex_unlock(&main_lock);
+    }
+
+    send_log("Status: %d", s);
+
+    if (s == NEXT) {
+
+      /* The status is to play a new song. Set
+         the status to PLAY and signal the thread
+         that the status has been processed.
+       */
+       
+      send_msg("I %s", fname);
+      send_msg("S 0.0 0 00000 xxxxxx 0 0 0 0 0 0 0 0");
+      pthread_mutex_lock(&main_lock);
+      setstatus(PLAY);
+      s = getstatus();
+      send_log("mainloop s=%d", s);
+      sem_post(&sem_processed);
+      s = getstatus();
+      send_log("mainloop s=%d", s);
+      pthread_mutex_unlock(&main_lock);
+
+      /* Start the player. The player calls the playloop
+         frequently to check for a new status (e.g. NEXT,
+         STOP or PAUSE.
+       */
+
+      pthread_mutex_lock(&main_lock);
+      s = getstatus();
+      pthread_mutex_unlock(&main_lock);
+      send_log("mainloop s=%d", s);
+      play(fname);
+      
+      /* Retrieve the new status */
+      pthread_mutex_lock(&main_lock);
+      s = getstatus();
+      pthread_mutex_unlock(&main_lock);
+
+      if (s == NEXT) {
+	  
+	    /* Send "play stopped" */
+        send_msg("P 0");
+        send_log("P 0");
+      } else {
+	  
+	    /* Send "play stopped at eof" */
+        send_msg("P 0 EOF");
+        send_log("P 0 EOF");
+      }
+      
+    }
+    else {
+
+      /* Irrelevent status, notice the thread that
+         it has been processed.
+       */
+       
+      sem_post(&sem_processed);
+    }    
+  }
+
+  /* Send "Quit" */
+  send_msg("Q");
+  send_log("Quit");
+
+  /* Cleanup the semaphores */
+  sem_destroy(&sem_command);
+  sem_destroy(&sem_processed);
+
+  return;
+}
+
+int remote_playloop(void) {
+
+  Status s;
+
+  /* Check the status. If the player should pause,
+     then signal that the command has been processed
+     and wait for a new status. A new status will end
+     the player and return control to the main loop.
+     The main loop will signal that the new command
+     has been processed.
+   */
+  
+  pthread_mutex_lock (&main_lock);
+  s = getstatus();
+  pthread_mutex_unlock (&main_lock);
+
+  send_log("playloop entry s=%d", s);
+
+  if (s == PAUSE) {
+
+    /* Send "pause on" */
+    send_msg("P 1");
+
+    while (s == PAUSE) {
+
+      sem_post(&sem_processed);
+      sem_wait(&sem_command);
+      pthread_mutex_lock (&main_lock);
+      s = getstatus();
+      pthread_mutex_unlock (&main_lock);
+    }
+
+    /* Send "pause off" */
+    send_msg("P 2");
+  }
+
+  send_log("playloop exit s=%d", s);
+
+  return ((s == NEXT) || (s == STOP) || (s == QUIT));
+}
+
+void remote_time(double current, double total, long bitrate) {
+
+  /* Send the frame (not implemented yet) the time and current bitrate */
+  send_msg("F 0 0 %.2f %.2f %li", current, (total-current), (bitrate/1024));
+  
+  return;
+}

Added: trunk/vorbis-tools/ogg123/remote.h
===================================================================
--- trunk/vorbis-tools/ogg123/remote.h	2006-12-16 23:45:16 UTC (rev 12216)
+++ trunk/vorbis-tools/ogg123/remote.h	2006-12-17 00:32:14 UTC (rev 12217)
@@ -0,0 +1,22 @@
+/* remote.h by Richard van Paasen <rvpaasen at dds.nl> */
+
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
+ * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
+ * PLEASE READ THESE TERMS BEFORE DISTRIBUTING.                     *
+ *                                                                  *
+ * THE Ogg123 SOURCE CODE IS (C) COPYRIGHT 2000-2001                *
+ * by Kenneth C. Arnold <ogg at arnoldnet.net> AND OTHER CONTRIBUTORS  *
+ * http://www.xiph.org/                                             *
+ *                                                                  *
+ ********************************************************************
+
+ last mod: $Id: remote.h,v 1.1 2002/11/20 00:03:34 rvpaasen Exp $
+
+ ********************************************************************/
+
+void remote_mainloop(void);
+int remote_playloop(void);
+void remote_time(double current, double total, long bitrate);



More information about the commits mailing list