[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