[xiph-cvs] cvs commit: vorbis-tools/vorbiscomment Makefile.am vcedit.c
Stan Seibert
volsung at xiph.org
Tue Dec 18 18:53:02 PST 2001
volsung 01/12/18 18:53:01
Modified: . acinclude.m4 configure.in
ogg123 Makefile.am buffer.c buffer.h ogg123.1 ogg123.c
ogg123.h ogg123rc-example
oggenc Makefile.am
ogginfo Makefile.am
share Makefile.am
vcut vcut.c
vorbiscomment Makefile.am vcedit.c
Added: ogg123 audio.c audio.h callbacks.c callbacks.h
cfgfile_options.c cfgfile_options.h
cmdline_options.c cmdline_options.h compat.h
file_transport.c format.c format.h http_transport.c
oggvorbis_format.c status.c status.h transport.c
transport.h
Removed: ogg123 nullbuffer.c
Log:
Finally, we merge my branch onto the head. Duck and cover.
Revision Changes Path
1.14 +291 -63 vorbis-tools/acinclude.m4
Index: acinclude.m4
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/acinclude.m4,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- acinclude.m4 2001/10/28 02:51:16 1.13
+++ acinclude.m4 2001/12/19 02:52:52 1.14
@@ -28,7 +28,7 @@
OGG_CFLAGS="-I$ogg_includes"
elif test "x$ogg_prefix" != "x" ; then
OGG_CFLAGS="-I$ogg_prefix/include"
- elif test "$prefix" != "xNONE"; then
+ elif test "x$prefix" != "xNONE"; then
OGG_CFLAGS="-I$prefix/include"
fi
@@ -102,68 +102,6 @@
rm -f conf.oggtest
])
-dnl Shamelessly stolen from Joerg Schilling's star.
-dnl Copyright 1998 J. Schilling
-
-dnl Checks if mmap() works to get shared memory
-dnl Defines HAVE_SMMAP on success.
-AC_DEFUN(AC_FUNC_SMMAP,
-[AC_CACHE_CHECK([if mmap works to get shared memory], ac_cv_func_smmap,
- [AC_TRY_RUN([
-#include <sys/types.h>
-#include <sys/mman.h>
-
-char *
-mkshare()
-{
- int size = 8192;
- int f;
- char *addr;
-
- if ((f = open("/dev/zero", 2)) < 0)
- exit(1);
- addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, f, 0);
- if (addr == (char *)-1)
- exit(1);
- close(f);
-
- return (addr);
-}
-
-main()
-{
- char *addr;
-
- addr = mkshare(8192);
- *addr = 'I';
-
- switch (fork()) {
-
- case -1:
- printf("help\n"); exit(1);
-
- case 0: /* child */
- *addr = 'N';
- _exit(0);
- break;
- default: /* parent */
- wait(0);
- sleep(1);
- break;
- }
-
- if (*addr != 'N')
- exit(1);
- exit(0);
-}
-],
- [ac_cv_func_smmap=yes],
- [ac_cv_func_smmap=no],
- [ac_cv_func_smmap=no])])
-if test $ac_cv_func_smmap = yes; then
- AC_DEFINE(HAVE_SMMAP)
-fi])
-
# Configure paths for libvorbis
# Jack Moffitt <jack at icecast.org> 10-21-2000
# Shamelessly stolen from Owen Taylor and Manish Singh
@@ -471,4 +409,294 @@
AC_DEFINE(HAVE_LANGINFO_CODESET, 1,
[Define if you have <langinfo.h> and nl_langinfo(CODESET).])
fi
+])
+
+dnl AM_PATH_CURL([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl Test for libcurl, and define CURL_CFLAGS and CURL_LIBS
+dnl
+AC_DEFUN(AM_PATH_CURL,
+[dnl
+dnl Get the cflags and libraries
+dnl
+AC_ARG_WITH(curl,[ --with-curl=PFX Prefix where libcurl is installed (optional)], curl_prefix="$withval", curl_prefix="")
+AC_ARG_WITH(curl-libraries,[ --with-curl-libraries=DIR Directory where libcurl library is installed (optional)], curl_libraries="$withval", curl_libraries="")
+AC_ARG_WITH(curl-includes,[ --with-curl-includes=DIR Directory where libcurl header files are installed (optional)], curl_includes="$withval", curl_includes="")
+AC_ARG_ENABLE(curltest, [ --disable-curltest Do not try to compile and run a test libcurl program],, enable_curltest=yes)
+
+ if test "x$curl_libraries" != "x" ; then
+ CURL_LIBS="-L$curl_libraries"
+ elif test "x$curl_prefix" != "x" ; then
+ CURL_LIBS="-L$curl_prefix/lib"
+ elif test "x$prefix" != "xNONE" ; then
+ CURL_LIBS="-L$prefix/lib"
+ fi
+
+ CURL_LIBS="$CURL_LIBS -lcurl"
+
+ if test "x$curl_includes" != "x" ; then
+ CURL_CFLAGS="-I$curl_includes"
+ elif test "x$curl_prefix" != "x" ; then
+ CURL_CFLAGS="-I$curl_prefix/include"
+ elif test "x$prefix" != "xNONE"; then
+ CURL_CFLAGS="-I$prefix/include"
+ fi
+
+ AC_MSG_CHECKING(for libcurl)
+ no_curl=""
+
+
+ if test "x$enable_curltest" = "xyes" ; then
+ ac_save_CFLAGS="$CFLAGS"
+ ac_save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $CURL_CFLAGS"
+ LIBS="$LIBS $CURL_LIBS"
+dnl
+dnl Now check if the installed libcurl is sufficiently new.
+dnl
+ rm -f conf.curltest
+ AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <curl/curl.h>
+
+int main ()
+{
+ system("touch conf.curltest");
+ return 0;
+}
+
+],, no_curl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+
+ if test "x$no_curl" = "x" ; then
+ AC_MSG_RESULT(yes)
+ ifelse([$1], , :, [$1])
+ else
+ AC_MSG_RESULT(no)
+ if test -f conf.curltest ; then
+ :
+ else
+ echo "*** Could not run libcurl test program, checking why..."
+ CFLAGS="$CFLAGS $CURL_CFLAGS"
+ LIBS="$LIBS $CURL_LIBS"
+ AC_TRY_LINK([
+#include <stdio.h>
+#include <curl/curl.h>
+], [ return 0; ],
+ [ echo "*** The test program compiled, but did not run. This usually means"
+ echo "*** that the run-time linker is not finding libcurl or finding the wrong"
+ echo "*** version of libcurl. If it is not finding libcurl, you'll need to set your"
+ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+ echo "*** to the installed location Also, make sure you have run ldconfig if that"
+ echo "*** is required on your system"
+ echo "***"
+ echo "*** If you have an old version installed, it is best to remove it, although"
+ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+ [ echo "*** The test program failed to compile or link. See the file config.log for the"
+ echo "*** exact error that occured. This usually means libcurl was incorrectly installed"
+ echo "*** or that you have moved libcurl since it was installed." ])
+ CFLAGS="$ac_save_CFLAGS"
+ LIBS="$ac_save_LIBS"
+ fi
+ CURL_CFLAGS=""
+ CURL_LIBS=""
+ ifelse([$2], , :, [$2])
+ fi
+ AC_SUBST(CURL_CFLAGS)
+ AC_SUBST(CURL_LIBS)
+ rm -f conf.curltest
+])
+
+
+dnl ACX_PTHREAD macro by Steven G. Johnson <stevenj at alum.mit.edu> and
+dnl Alejandro Forero Cuervo <bachue at bachue.com>. Found at:
+dnl http://www.gnu.org/software/ac-archive/Installed_Packages/acx_pthread.html
+
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+acx_pthread_ok=no
+
+# First, check if the POSIX threads header, pthread.h, is available.
+# If it isn't, don't bother looking for the threads libraries.
+AC_CHECK_HEADER(pthread.h, , acx_pthread_ok=noheader)
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test x"$acx_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread pthread -pthread -pthreads -mthreads --thread-safe -mt"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+
+case "${host_cpu}-${host_os}" in
+ *solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthread or
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+ acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
+ ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_TRY_LINK([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0);
+ pthread_cancel(0); pthread_cleanup_pop(0); ],
+ [acx_pthread_ok=yes])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test "x$acx_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: threads are created detached by default
+ # and the JOINABLE attribute has a nonstandard name (UNDETACHED).
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ AC_TRY_LINK([#include <pthread.h>],
+ [int attr=PTHREAD_CREATE_JOINABLE;],
+ ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
+ if test x"$ok" = xunknown; then
+ AC_TRY_LINK([#include <pthread.h>],
+ [int attr=PTHREAD_CREATE_UNDETACHED;],
+ ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
+ fi
+ if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
+ [Define to the necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+ AC_MSG_RESULT(${ok})
+ if test x"$ok" = xunknown; then
+ AC_MSG_WARN([we do not know how to create joinable pthreads])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case "${host_cpu}-${host_os}" in
+ *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";;
+ *solaris* | alpha*-osf*) flag="-D_REENTRANT";;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with cc_r
+ AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+else
+ PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+ :
+else
+ acx_pthread_ok=no
+ $2
+fi
+
])
1.32 +10 -19 vorbis-tools/configure.in
Index: configure.in
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/configure.in,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- configure.in 2001/10/02 03:03:41 1.31
+++ configure.in 2001/12/19 02:52:52 1.32
@@ -19,13 +19,7 @@
AM_PROG_LIBTOOL
-dnl --------------------------------------------------
-dnl Additional arguments
-dnl --------------------------------------------------
-AC_ARG_WITH(ogg, [ --with-ogg=DIR Set where the Ogg library is located])
-AC_ARG_WITH(vorbis, [ --with-vorbis=DIR Set where the Vorbis library is located])
-
dnl --------------------------------------------------
dnl Set build flags based on environment
dnl --------------------------------------------------
@@ -82,35 +76,29 @@
LDFLAGS="$LDFLAGS $ldflags_save"
dnl --------------------------------------------------
-dnl Check for headers
-dnl --------------------------------------------------
-
-dnl none
-
-dnl --------------------------------------------------
-dnl Check for typedefs, structures, etc
-dnl --------------------------------------------------
-
-dnl none
-
-dnl --------------------------------------------------
dnl Check for libraries
dnl --------------------------------------------------
AM_PATH_OGG(,AC_MSG_ERROR(Ogg needed!))
AM_PATH_VORBIS(,AC_MSG_ERROR(Vorbis needed!))
AM_PATH_AO(,AC_MSG_ERROR(libao needed!))
+AM_PATH_CURL(,AC_MSG_ERROR(libcurl needed!))
+
+ACX_PTHREAD(,AC_MSG_ERROR(POSIX threads required!))
+
SOCKET_LIBS=
AC_CHECK_LIB(socket, socket, SOCKET_LIBS="-lsocket")
AC_CHECK_LIB(nsl, gethostbyname, SOCKET_LIBS="-lnsl $SOCKET_LIBS")
+
SHARE_LIBS='$(top_srcdir)/share/libutf8.a $(top_srcdir)/share/libgetopt.a'
+SHARE_CFLAGS='-I$(top_srcdir)/include'
dnl --------------------------------------------------
dnl Check for library functions
dnl --------------------------------------------------
AM_ICONV
-AC_FUNC_SMMAP
+AC_CHECK_FUNCS(atexit on_exit)
AM_LANGINFO_CODESET
dnl --------------------------------------------------
@@ -131,6 +119,9 @@
AC_SUBST(DEBUG)
AC_SUBST(PROFILE)
AC_SUBST(SOCKET_LIBS)
+AC_SUBST(SHARE_CFLAGS)
AC_SUBST(SHARE_LIBS)
+AC_SUBST(CURL_CFLAGS)
+AC_SUBST(CURL_LIBS)
AC_OUTPUT(Makefile include/Makefile share/Makefile oggenc/Makefile oggenc/man/Makefile ogg123/Makefile vorbiscomment/Makefile vcut/Makefile ogginfo/Makefile debian/Makefile)
1.17 +11 -6 vorbis-tools/ogg123/Makefile.am
Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/Makefile.am,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- Makefile.am 2001/09/22 22:49:49 1.16
+++ Makefile.am 2001/12/19 02:52:53 1.17
@@ -8,15 +8,20 @@
mandir = @MANDIR@
man_MANS = ogg123.1
-INCLUDES = @OGG_CFLAGS@ @VORBIS_CFLAGS@ @AO_CFLAGS@
+INCLUDES = @OGG_CFLAGS@ @VORBIS_CFLAGS@ @AO_CFLAGS@ @CURL_CFLAGS@ \
+ @PTHREAD_CFLAGS@ @SHARE_CFLAGS@
ogg123_LDADD = @VORBISFILE_LIBS@ @VORBIS_LIBS@ @OGG_LIBS@ @AO_LIBS@ \
- @SOCKET_LIBS@ @SHARE_LIBS@
+ @SOCKET_LIBS@ @SHARE_LIBS@ @CURL_LIBS@ @PTHREAD_CFLAGS@ \
+ @PTHREAD_LIBS@
ogg123_DEPENDENCIES = @SHARE_LIBS@
-
-ogg123_SOURCES = ogg123.c ao_interface.c buffer.c ogg123.h buffer.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
+ogg123_SOURCES = audio.c buffer.c callbacks.c \
+ cfgfile_options.c cmdline_options.c \
+ file_transport.c format.c http_transport.c \
+ ogg123.c oggvorbis_format.c status.c transport.c \
+ audio.h buffer.h callbacks.h compat.h \
+ cfgfile_options.h cmdline_options.h \
+ format.h ogg123.h status.h transport.h
EXTRA_DIST = $(man_MANS) $(doc_DATA)
1.9 +664 -166 vorbis-tools/ogg123/buffer.c
Index: buffer.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/buffer.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- buffer.c 2001/10/02 03:10:42 1.8
+++ buffer.c 2001/12/19 02:52:53 1.9
@@ -1,210 +1,708 @@
-/* buffer.c
- * buffering code for ogg123. This is Unix-specific. Other OSes anyone?
- *
- * Thanks to Lee McLouchlin's buffer(1) for inspiration; no code from
- * that program is used in this buffer.
- */
+/********************************************************************
+ * *
+ * 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: buffer.c,v 1.9 2001/12/19 02:52:53 volsung Exp $
+
+ ********************************************************************/
+
+
#include <sys/types.h>
-#if HAVE_SMMAP
-#include <sys/mman.h>
-#else
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#endif
+#include <sys/wait.h>
#include <sys/time.h>
-#include <unistd.h> /* for fork and pipe*/
+#include <string.h>
#include <fcntl.h>
#include <signal.h>
+#include <unistd.h>
+#include <stdio.h>
-#include "ogg123.h"
+#include "compat.h"
#include "buffer.h"
+
+#define MIN(x,y) ( (x) < (y) ? (x) : (y) )
+#define MIN3(x,y,z) MIN(x,MIN(y,z))
+#define MIN4(w,x,y,z) MIN( MIN(w,x), MIN(y,z) )
+
+/* Special debugging code. THIS IS NOT PORTABLE! */
+#ifdef DEBUG_BUFFER
+FILE *debugfile;
+#define DEBUG(x, y...) { fprintf (debugfile, "%d: " x "\n", getpid(), ## y); }
+#else
+#define DEBUG(x, y...)
+#endif
+
+/* Macros that support debugging of threading structures */
+
+#define LOCK_MUTEX(mutex) { DEBUG("Locking mutex %s.", #mutex); pthread_mutex_lock (&(mutex)); }
+#define UNLOCK_MUTEX(mutex) { DEBUG("Unlocking mutex %s", #mutex); pthread_mutex_unlock(&(mutex)); }
+#define COND_WAIT(cond, mutex) { DEBUG("Unlocking %s and waiting on %s", #mutex, #cond); pthread_cond_wait(&(cond), &(mutex)); }
+#define COND_SIGNAL(cond) { DEBUG("Signalling %s", #cond); pthread_cond_signal(&(cond)); }
+
+
+/* -------------------- Private Functions ------------------ */
+
+void buffer_init_vars (buf_t *buf)
+{
+ /* Initialize buffer flags */
+ buf->prebuffering = buf->prebuffer_size > 0;
+ buf->paused = 0;
+ buf->eos = 0;
+ buf->abort_write = 0;
+
+ buf->curfill = 0;
+ buf->start = 0;
+ buf->position = 0;
+ buf->position_end = 0;
+}
-/* Initialize the buffer structure. */
-void buffer_init (buf_t *buf, long size)
+void buffer_thread_init (buf_t *buf)
{
- buf->status = 0;
- buf->reader = buf->writer = buf->buffer;
- buf->end = buf->buffer + (size - 1);
+ sigset_t set;
+
+ DEBUG("Enter buffer_thread_init");
+
+ /* Block signals to this thread */
+ sigfillset(&set);
+ sigaddset(&set, SIGINT);
+ sigaddset(&set, SIGTSTP);
+ sigaddset(&set, SIGCONT);
+ if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0)
+ DEBUG("pthread_sigmask failed");
}
-/* Main write loop. No semaphores. No deadlock. No problem. I hope. */
-void writer_main (volatile buf_t *buf, devices_t *d)
+
+void buffer_thread_cleanup (void *arg)
{
- devices_t *d1;
- signal (SIGINT, SIG_IGN);
+ buf_t *buf = (buf_t *)arg;
+
+ DEBUG("Enter buffer_thread_cleanup");
+
+ /* Cleanup thread data structures */
+ pthread_mutex_unlock(&buf->mutex);
+ pthread_mutex_destroy(&buf->mutex);
+ pthread_cond_destroy(&buf->playback_cond);
+ pthread_cond_destroy(&buf->write_cond);
+}
- while (! (buf->status & STAT_SHUTDOWN && buf->reader == buf->writer))
- {
- /* Writer just waits on reader to be done with buf_write.
- * Reader must ensure that we don't deadlock. */
- write (buf->fds[1], "1", 1); /* This identifier could hold a lot
- * more detail in the future. */
+action_t *malloc_action (action_func_t action_func, void *action_arg)
+{
+ action_t *action;
- if (buf->status & STAT_FLUSH) {
- buf->reader = buf->writer;
- buf->status &= ~STAT_FLUSH;
- }
+ action = malloc(sizeof(action_t));
+
+ if (action == NULL) {
+ fprintf(stderr, "Error: Out of memory in malloc_action().\n");
+ exit(1);
+ }
+
+ action->position = 0;
+ action->action_func = action_func;
+ action->arg = action_arg;
+ action->next = NULL;
- while (buf->reader == buf->writer && !(buf->status & STAT_SHUTDOWN));
+ return action;
+}
- if (buf->reader == buf->writer) break;
- /* devices_write (buf->writer->data, buf->writer->len, d); */
- {
- d1 = d;
- while (d1 != NULL) {
- ao_play(d1->device, buf->writer->data, buf->writer->len);
- d1 = d1->next_device;
- }
- }
+/* insert = 1: Make this action the first action associated with this position
+ insert = 0: Make this action the last action associated with this position
+*/
+#define INSERT 1
+#define APPEND 0
+void in_order_add_action (action_t **action_list, action_t *action, int insert)
+{
+ insert = insert > 0 ? 1 : 0; /* Clamp in case caller messed up */
+
+ while (*action_list != NULL &&
+ (*action_list)->position <= (action->position + insert))
+ action_list = &((*action_list)->next);
- if (buf->writer == buf->end)
- buf->writer = (chunk_t *)buf->buffer;
- else
- buf->writer++;
- }
- buf->status = 0;
- write (buf->fds[1], "2", 1);
- _exit(0);
+ action->next = *action_list;
+ *action_list = action;
}
-/* fork_writer is called to create the writer process. This creates
- * the shared memory segment of 'size' chunks, and returns a pointer
- * to the buffer structure that is shared. Just pass this straight to
- * submit_chunk and all will be happy. */
-buf_t *fork_writer (long size, devices_t *d)
+void execute_actions (buf_t *buf, action_t **action_list, ogg_int64_t position)
{
- int childpid;
- buf_t *buf;
+ action_t *action;
-#if HAVE_SMMAP
- int fd;
+ while (*action_list != NULL && (*action_list)->position <= position) {
+ action = *action_list;
+ action->action_func(buf, action->arg);
+
+ *action_list = (*action_list)->next;
+ free(action);
+ }
+}
- if ((fd = open("/dev/zero", O_RDWR)) < 0)
- {
- perror ("cannot open /dev/zero");
- exit (1);
+
+void free_action (action_t *action)
+{
+ free(action);
+}
+
+
+
+int compute_dequeue_size (buf_t *buf, int request_size)
+{
+ int next_action_pos;
+
+ /*
+ For simplicity, the number of bytes played must satisfy the following
+ requirements:
+ 1. Do not extract more bytes than are stored in the buffer.
+ 2. Do not extract more bytes than the requested number of bytes.
+ 3. Do not run off the end of the buffer.
+ 4. Do not go past the next action.
+ */
+
+ if (buf->actions != NULL) {
+
+ next_action_pos = buf->actions->position;
+
+ return MIN4(buf->curfill, request_size,
+ buf->size - buf->start, next_action_pos - buf->position);
+ } else
+ return MIN3(buf->curfill, request_size, buf->size - buf->start);
+
+}
+
+
+void *buffer_thread_func (void *arg)
+{
+ buf_t *buf = (buf_t*) arg;
+ size_t write_amount;
+
+ DEBUG("Enter buffer_thread_func");
+
+ buffer_thread_init(buf);
+
+ pthread_cleanup_push(buffer_thread_cleanup, buf);
+
+ DEBUG("Start main play loop");
+
+ /* This test is safe since curfill will never decrease and eos will
+ never be unset. */
+ while ( !(buf->eos && buf->curfill == 0) ) {
+
+ DEBUG("Check for something to play");
+ /* Block until we can play something */
+ LOCK_MUTEX (buf->mutex);
+ if (buf->prebuffering ||
+ buf->paused ||
+ (buf->curfill < buf->audio_chunk_size && !buf->eos)) {
+
+ DEBUG("Waiting for more data to play.");
+ COND_WAIT(buf->playback_cond, buf->mutex);
}
- if ((buf = (buf_t *) mmap (0, sizeof(buf_t) + sizeof (chunk_t) * (size - 1),
- PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED)
- {
- perror("mmap");
- exit(1);
+
+ DEBUG("Ready to play");
+
+ UNLOCK_MUTEX(buf->mutex);
+
+ pthread_testcancel();
+
+ /* Don't need to lock buffer while running actions since position
+ won't change. We clear out any actions before we compute the
+ dequeue size so we don't consider actions that need to
+ run right now. */
+ execute_actions(buf, &buf->actions, buf->position);
+
+ LOCK_MUTEX(buf->mutex);
+
+ /* Need to be locked while we check things. */
+ write_amount = compute_dequeue_size(buf, buf->audio_chunk_size);
+
+ pthread_testcancel();
+
+ UNLOCK_MUTEX(buf->mutex);
+
+ /* No need to lock mutex here because the other thread will
+ NEVER reduce the number of bytes stored in the buffer */
+ DEBUG("Sending %d bytes to the audio device", write_amount);
+ buf->write_func(buf->buffer + buf->start, write_amount,
+ /* Only set EOS if this is the last chunk */
+ write_amount == buf->curfill ? buf->eos : 0,
+ buf->write_arg);
+
+ LOCK_MUTEX(buf->mutex);
+
+ buf->curfill -= write_amount;
+ buf->position += write_amount;
+ buf->start = (buf->start + write_amount) % buf->size;
+ DEBUG("Updated buffer fill, curfill = %ld, position = %ld", buf->curfill,
+ buf->position);
+
+ /* If we've essentially emptied the buffer and prebuffering is enabled,
+ we need to do another prebuffering session */
+ if (!buf->eos && (buf->curfill < buf->audio_chunk_size))
+ buf->prebuffering = buf->prebuffer_size > 0;
+
+ /* Signal a waiting decoder thread that they can put more audio into the
+ buffer */
+ DEBUG("Signal decoder thread that buffer space is available");
+ COND_SIGNAL(buf->write_cond);
+
+ UNLOCK_MUTEX(buf->mutex);
+ }
+
+ pthread_cleanup_pop(1);
+ DEBUG("exiting buffer_thread_func");
+
+ return 0;
+}
+
+
+void submit_data_chunk (buf_t *buf, char *data, size_t size)
+{
+ long buf_write_pos; /* offset of first available write location */
+ size_t write_size;
+
+ DEBUG("Enter submit_data_chunk, size %d", size);
+
+ /* Put the data into the buffer as space is made available */
+ while (size > 0) {
+
+ /* Section 1: Write a chunk of data */
+ DEBUG("Obtaining lock on buffer");
+ LOCK_MUTEX(buf->mutex);
+ if (buf->size - buf->curfill > 0) {
+
+ /* Figure how much we can write into the buffer. Requirements:
+ 1. Don't write more data than we have.
+ 2. Don't write more data than we have room for.
+ 3. Don't write past the end of the buffer. */
+ buf_write_pos = (buf->start + buf->curfill) % buf->size;
+ write_size = MIN3(size, buf->size - buf->curfill,
+ buf->size - buf_write_pos);
+
+ memcpy(buf->buffer + buf_write_pos, data, write_size);
+ buf->curfill += write_size;
+ data += write_size;
+ size -= write_size;
+ buf->position_end += write_size;
+ DEBUG("writing chunk into buffer, curfill = %ld", buf->curfill);
}
- close(fd);
-#else
- /* Get the shared memory segment. */
- int shmid = shmget (IPC_PRIVATE,
- sizeof(buf_t) + sizeof (chunk_t) * (size - 1),
- IPC_CREAT|SHM_R|SHM_W);
-
- if (shmid == -1)
- {
- perror ("shmget");
- exit (1);
+ else {
+
+ /* No room for more data, wait until there is */
+ DEBUG("No room for data in buffer. Waiting.");
+ COND_WAIT(buf->write_cond, buf->mutex);
+ }
+
+ /* Section 2: signal if we are not prebuffering, done
+ prebuffering, or paused */
+ if (buf->prebuffering && (buf->prebuffer_size <= buf->curfill)) {
+
+ DEBUG("prebuffering done")
+ buf->prebuffering = 0; /* done prebuffering */
}
+
+ if (!buf->prebuffering && !buf->paused) {
+
+ DEBUG("Signalling playback thread that more data is available.");
+ COND_SIGNAL(buf->playback_cond);
+ } else
+ DEBUG("Not signalling playback thread since prebuffering or paused.");
+
+ UNLOCK_MUTEX(buf->mutex);
+ }
+
+ DEBUG("Exit submit_data_chunk");
+}
+
+
+buffer_stats_t *malloc_buffer_stats ()
+{
+ buffer_stats_t *new_stats;
+
+ new_stats = malloc(sizeof(buffer_stats_t));
+
+ if (new_stats == NULL) {
+ fprintf(stderr, "Error: Could not allocate memory in malloc_buffer_stats()\n");
+ exit(1);
+ }
+
+ return new_stats;
+}
+
+
+/* ------------------ Begin public interface ------------------ */
+
+/* --- Buffer allocation --- */
+
+buf_t *buffer_create (long size, long prebuffer,
+ buffer_write_func_t write_func, void *arg,
+ int audio_chunk_size)
+{
+ buf_t *buf = malloc (sizeof(buf_t) + sizeof (char) * (size - 1));
+
+ if (buf == NULL) {
+ perror ("malloc");
+ exit(1);
+ }
+
+#ifdef DEBUG_BUFFER
+ debugfile = fopen ("/tmp/bufferdebug", "w");
+ setvbuf (debugfile, NULL, _IONBF, 0);
+#endif
+
+ /* Initialize the buffer structure. */
+ DEBUG("buffer_create, size = %ld", size);
+
+ memset (buf, 0, sizeof(*buf));
+
+ buf->write_func = write_func;
+ buf->write_arg = arg;
+
+ /* Setup pthread variables */
+ pthread_mutex_init(&buf->mutex, NULL);
+ pthread_cond_init(&buf->write_cond, NULL);
+ pthread_cond_init(&buf->playback_cond, NULL);
- /* Attach the segment to us (and our kids). Get and store the pointer. */
- buf = (buf_t *) shmat (shmid, 0, 0);
+ /* Correct for impossible chunk sizes */
+ if (audio_chunk_size > size || audio_chunk_size == 0)
+ audio_chunk_size = size / 2;
+
+ buf->audio_chunk_size = audio_chunk_size;
+
+ buf->prebuffer_size = prebuffer;
+ buf->size = size;
+
+ buf->actions = 0;
+
+ /* Initialize flags */
+ buffer_init_vars(buf);
+
+ return buf;
+}
+
+
+void buffer_reset (buf_t *buf)
+{
+ action_t *action;
+
+ /* Cleanup pthread variables */
+ pthread_mutex_destroy(&buf->mutex);
+ pthread_cond_destroy(&buf->write_cond);
+ pthread_cond_destroy(&buf->playback_cond);
- if (buf == NULL)
- {
- perror ("shmat");
- exit (1);
- }
+ /* Reinit pthread variables */
+ pthread_mutex_init(&buf->mutex, NULL);
+ pthread_cond_init(&buf->write_cond, NULL);
+ pthread_cond_init(&buf->playback_cond, NULL);
+
+ /* Clear old actions */
+ while (buf->actions != NULL) {
+ action = buf->actions;
+ buf->actions = buf->actions->next;
+ free(action);
+ }
- /* Remove segment after last process detaches it or terminates. */
- shmctl(shmid, IPC_RMID, 0);
-#endif /* HAVE_SMMAP */
-
- buffer_init (buf, size);
-
- /* Create a pipe for communication between the two processes. Unlike
- * the first incarnation of an ogg123 buffer, the data is not transferred
- * over this channel, only occasional "WAKE UP!"'s. */
-
- if (pipe (buf->fds))
- {
- perror ("pipe");
- exit (1);
- }
+ buffer_init_vars(buf);
+}
+
+
+void buffer_destroy (buf_t *buf)
+{
+ DEBUG("buffer_destroy");
+ free(buf);
+}
+
+
+/* --- Buffer thread control --- */
- fcntl (buf->fds[1], F_SETFL, O_NONBLOCK);
- /* write should never block; read should always block. */
+int buffer_thread_start (buf_t *buf)
+{
+ DEBUG("Starting new thread.");
+
+ return pthread_create(&buf->thread, NULL, buffer_thread_func, buf);
+}
+
+
+/* WARNING: DO NOT call buffer_submit_data after you pause the
+ playback thread, or you run the risk of deadlocking. Call
+ buffer_thread_unpause first. */
+void buffer_thread_pause (buf_t *buf)
+{
+ DEBUG("Pausing playback thread");
+
+ LOCK_MUTEX(buf->mutex);
+ buf->paused = 1;
+ UNLOCK_MUTEX(buf->mutex);
+}
+
- fflush (stdout);
- /* buffer flushes stderr, but stderr is unbuffered (*duh*!) */
+void buffer_thread_unpause (buf_t *buf)
+{
+ DEBUG("Unpausing playback thread");
- childpid = fork();
+ LOCK_MUTEX(buf->mutex);
+ buf->paused = 0;
+ COND_SIGNAL(buf->playback_cond);
+ UNLOCK_MUTEX(buf->mutex);
+}
+
+
+void buffer_thread_kill (buf_t *buf)
+{
+ DEBUG("Attempting to kill playback thread.");
+
+ /* End thread */
+ pthread_cancel (buf->thread);
- if (childpid == -1)
- {
- perror ("fork");
- exit (1);
- }
+ /* Signal all the playback condition to wake stuff up */
+ COND_SIGNAL(buf->playback_cond);
- if (childpid == 0)
- {
- writer_main (buf, d);
- return NULL;
- }
- else
- return buf;
+ pthread_join(buf->thread, NULL);
+
+ buffer_thread_cleanup(buf);
+
+ DEBUG("Playback thread killed.");
+}
+
+
+/* --- Data buffering functions --- */
+
+void buffer_submit_data (buf_t *buf, char *data, long nbytes)
+{
+ submit_data_chunk (buf, data, nbytes);
}
-void submit_chunk (buf_t *buf, chunk_t chunk)
+size_t buffer_get_data (buf_t *buf, char *data, long nbytes)
{
- struct timeval tv;
- static fd_set set;
+ int write_amount;
+ int orig_size;
- FD_ZERO(&set);
- FD_SET(buf->fds[0], &set);
+ orig_size = nbytes;
- /* Wait wait, don't step on my sample! */
- while (!((buf->reader != buf->end && buf->reader + 1 != buf->writer) ||
- (buf->reader == buf->end && buf->writer != buf->buffer)))
- {
- /* buffer overflow (yikes! no actually it's a GOOD thing) */
- int ret;
- char t;
-
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- ret = select (buf->fds[0]+1, &set, NULL, NULL, &tv);
+ DEBUG("Enter buffer_get_data");
+
+ LOCK_MUTEX(buf->mutex);
+
+ /* Put the data into the buffer as space is made available */
+ while (nbytes > 0) {
+
+ DEBUG("Obtaining lock on buffer");
+ /* Block until we can read something */
+ if (buf->curfill == 0) {
+ if (buf->eos)
+ break; /* No more data to read */
- while (ret-- > 0)
- read (buf->fds[0], &t, 1);
+ DEBUG("Waiting for more data to copy.");
+ COND_WAIT(buf->playback_cond, buf->mutex);
}
-
- *(buf->reader) = chunk;
- /* do this atomically */
- if (buf->reader == buf->end)
- buf->reader = buf->buffer;
- else
- buf->reader++;
-}
-
-void buffer_flush (buf_t *buf)
-{
- buf->status |= STAT_FLUSH;
-}
-
-void buffer_shutdown (buf_t *buf)
-{
- struct timeval tv;
-
- buf->status |= STAT_SHUTDOWN;
- while (buf->status != 0)
- {
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- select (0, NULL, NULL, NULL, &tv);
- }
-#ifndef HAVE_SMMAP
- /* Deallocate the shared memory segment. */
- shmdt(buf);
-#endif /* HAVE_SMMAP */
+
+ if (buf->abort_write)
+ break;
+
+ /* Note: Even if curfill is still 0, nothing bad will happen here */
+
+ /* For simplicity, the number of bytes played must satisfy
+ the following three requirements:
+
+ 1. Do not copy more bytes than are stored in the buffer.
+ 2. Do not copy more bytes than the reqested data size.
+ 3. Do not run off the end of the buffer. */
+ write_amount = compute_dequeue_size(buf, nbytes);
+
+ execute_actions(buf, &buf->actions, buf->position);
+
+ /* No need to lock mutex here because the other thread will
+ NEVER reduce the number of bytes stored in the buffer */
+ DEBUG("Copying %d bytes from the buffer", write_amount);
+ memcpy(data, buf->buffer + buf->start, write_amount);
+
+ buf->curfill -= write_amount;
+ data += write_amount;
+ nbytes -= write_amount;
+ buf->start = (buf->start + write_amount) % buf->size;
+ DEBUG("Updated buffer fill, curfill = %ld", buf->curfill);
+
+ /* Signal a waiting decoder thread that they can put more
+ audio into the buffer */
+ DEBUG("Signal decoder thread that buffer space is available");
+ COND_SIGNAL(buf->write_cond);
+ }
+
+ UNLOCK_MUTEX(buf->mutex);
+
+ pthread_testcancel();
+
+ DEBUG("Exit buffer_get_data");
+
+ return orig_size - nbytes;
+}
+
+void buffer_mark_eos (buf_t *buf)
+{
+ DEBUG("buffer_mark_eos");
+
+ LOCK_MUTEX(buf->mutex);
+ buf->eos = 1;
+ buf->prebuffering = 0;
+ COND_SIGNAL(buf->playback_cond);
+ UNLOCK_MUTEX(buf->mutex);
+}
+
+void buffer_abort_write (buf_t *buf)
+{
+ DEBUG("buffer_mark_eos");
+
+ LOCK_MUTEX(buf->mutex);
+ buf->abort_write = 1;
+ COND_SIGNAL(buf->write_cond);
+ UNLOCK_MUTEX(buf->mutex);
+}
+
+
+/* --- Action buffering functions --- */
+
+void buffer_action_now (buf_t *buf, action_func_t action_func,
+ void *action_arg)
+{
+ action_t *action;
+
+ action = malloc_action(action_func, action_arg);
+
+ LOCK_MUTEX(buf->mutex);
+
+ action->position = buf->position;
+
+ /* Insert this action right at the front */
+ action->next = buf->actions;
+ buf->actions = action;
+
+ UNLOCK_MUTEX(buf->mutex);
+}
+
+
+void buffer_insert_action_at_end (buf_t *buf, action_func_t action_func,
+ void *action_arg)
+{
+ action_t *action;
+
+ action = malloc_action(action_func, action_arg);
+
+ LOCK_MUTEX(buf->mutex);
+
+ /* Stick after the last item in the buffer */
+ action->position = buf->position_end;
+
+ in_order_add_action(&buf->actions, action, INSERT);
+
+ UNLOCK_MUTEX(buf->mutex);
+}
+
+
+void buffer_append_action_at_end (buf_t *buf, action_func_t action_func,
+ void *action_arg)
+{
+ action_t *action;
+
+ action = malloc_action(action_func, action_arg);
+
+ LOCK_MUTEX(buf->mutex);
+
+ /* Stick after the last item in the buffer */
+ action->position = buf->position_end;
+
+ in_order_add_action(&buf->actions, action, APPEND);
+
+ UNLOCK_MUTEX(buf->mutex);
}
+
+
+void buffer_insert_action_at (buf_t *buf, action_func_t action_func,
+ void *action_arg, ogg_int64_t position)
+{
+ action_t *action;
+
+ action = malloc_action(action_func, action_arg);
+
+ LOCK_MUTEX(buf->mutex);
+
+ action->position = position;
+
+ in_order_add_action(&buf->actions, action, INSERT);
+
+ UNLOCK_MUTEX(buf->mutex);
+}
+
+
+void buffer_append_action_at (buf_t *buf, action_func_t action_func,
+ void *action_arg, ogg_int64_t position)
+{
+ action_t *action;
+
+ action = malloc_action(action_func, action_arg);
+
+ LOCK_MUTEX(buf->mutex);
+
+ action->position = position;
+
+ in_order_add_action(&buf->actions, action, APPEND);
+
+ UNLOCK_MUTEX(buf->mutex);
+}
+
+
+/* --- Buffer status functions --- */
+
+void buffer_wait_for_empty (buf_t *buf)
+{
+ int empty = 0;
+
+ DEBUG("Enter buffer_wait_for_empty");
+
+ LOCK_MUTEX(buf->mutex);
+ while (!empty) {
+
+ if (buf->curfill > 0) {
+ DEBUG("Buffer curfill = %ld, going back to sleep.", buf->curfill);
+ COND_WAIT(buf->write_cond, buf->mutex);
+ } else
+ empty = 1;
+ }
+ UNLOCK_MUTEX(buf->mutex);
+
+ DEBUG("Exit buffer_wait_for_empty");
+}
+
+
+long buffer_full (buf_t *buf)
+{
+ return buf->curfill;
+}
+
+
+buffer_stats_t *buffer_statistics (buf_t *buf)
+{
+ buffer_stats_t *stats;
+
+ LOCK_MUTEX(buf->mutex);
+
+ stats = malloc_buffer_stats();
+
+ stats->size = buf->size;
+ stats->fill = (double) buf->curfill / (double) buf->size * 100.0;
+ stats->prebuffering = buf->prebuffering;
+ stats->paused = buf->paused;
+ stats->eos = buf->eos;
+
+ UNLOCK_MUTEX(buf->mutex);
+
+ return stats;
+}
+
+
1.4 +122 -27 vorbis-tools/ogg123/buffer.h
Index: buffer.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/buffer.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- buffer.h 2001/08/04 23:54:37 1.3
+++ buffer.h 2001/12/19 02:52:53 1.4
@@ -1,38 +1,133 @@
-/* Common things between reader and writer threads */
+/********************************************************************
+ * *
+ * 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: buffer.h,v 1.4 2001/12/19 02:52:53 volsung Exp $
+
+********************************************************************/
+
+/* A generic circular buffer interface with the ability to buffer
+ actions (conceptually) between bytes in the buffer.*/
+
+#ifndef __BUFFER_H__
+#define __BUFFER_H__
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <ogg/os_types.h>
-#ifndef __BUFFER_H
-#define __BUFFER_H
-#include "ogg123.h"
+struct action_t; /* forward declaration */
-/* 4096 is the chunk size we request from libvorbis. */
-#define BUFFER_CHUNK_SIZE 4096
+/* buffer_write_func(void *data, int nbytes, int eos, void *arg) */
+typedef int (*buffer_write_func_t) (void *, int, int, void *);
-typedef struct chunk_s
+typedef struct buf_t
{
- long len; /* Length of the chunk (for if we only got partial data) */
- char data[BUFFER_CHUNK_SIZE];
-} chunk_t;
+ /* generic buffer interface */
+ void *write_arg;
+ buffer_write_func_t write_func;
+
+ /* pthread variables */
+ pthread_t thread;
+
+ pthread_mutex_t mutex;
+
+ pthread_cond_t playback_cond; /* signalled when playback can continue */
+ pthread_cond_t write_cond; /* signalled when more data can be written
+ to the buffer */
+
+ /* buffer info (constant) */
+ int audio_chunk_size; /* write data to audio device in this chunk size,
+ if possible */
+ long prebuffer_size; /* number of bytes to prebuffer */
+ long size; /* buffer size, for reference */
+
+ /* ----- Everything after this point is protected by mutex ----- */
+
+ /* buffering state variables */
+ int prebuffering;
+ int paused;
+ int eos;
+ int abort_write;
+
+ /* buffer data */
+ long curfill; /* how much the buffer is currently filled */
+ long start; /* offset in buffer of start of available data */
+ ogg_int64_t position; /* How many bytes have we output so far */
+ ogg_int64_t position_end; /* Position right after end of data */
-typedef struct buf_s
-{
- char status; /* Status. See STAT_* below. */
- int fds[2]; /* Pipe file descriptors. */
- chunk_t *reader; /* Chunk the reader is busy with */
- chunk_t *writer; /* Chunk the writer is busy with */
- chunk_t *end; /* Last chunk in the buffer (for convenience) */
- chunk_t buffer[1]; /* The buffer itself. It's more than one chunk. */
+ struct action_t *actions; /* Queue actions to perform */
+ char buffer[1]; /* The buffer itself. It's more than one byte. */
} buf_t;
-buf_t *fork_writer (long size, devices_t *d);
-void submit_chunk (buf_t *buf, chunk_t chunk);
-void buffer_shutdown (buf_t *buf);
-void buffer_flush (buf_t *buf);
-
-#define STAT_FLUSH 1
-#define STAT_SHUTDOWN 2
-
-#endif /* !defined (__BUFFER_H) */
+/* action_func(buf_t *buf, void *arg) */
+typedef void (*action_func_t) (buf_t *, void *);
+typedef struct action_t {
+ ogg_int64_t position;
+ action_func_t action_func;
+ void *arg;
+ struct action_t *next;
+} action_t;
+
+
+typedef struct buffer_stats_t {
+ long size;
+ double fill;
+ int prebuffering;
+ int paused;
+ int eos;
+} buffer_stats_t;
+
+
+/* --- Buffer allocation --- */
+
+buf_t *buffer_create (long size, long prebuffer,
+ buffer_write_func_t write_func, void *arg,
+ int audio_chunk_size);
+
+void buffer_reset (buf_t *buf);
+void buffer_destroy (buf_t *buf);
+
+/* --- Buffer thread control --- */
+int buffer_thread_start (buf_t *buf);
+void buffer_thread_pause (buf_t *buf);
+void buffer_thread_unpause (buf_t *buf);
+void buffer_thread_kill (buf_t *buf);
+
+/* --- Data buffering functions --- */
+void buffer_submit_data (buf_t *buf, char *data, long nbytes);
+size_t buffer_get_data (buf_t *buf, char *data, long nbytes);
+
+void buffer_mark_eos (buf_t *buf);
+void buffer_abort_write (buf_t *buf);
+
+/* --- Action buffering functions --- */
+void buffer_action_now (buf_t *buf, action_func_t action_func,
+ void *action_arg);
+void buffer_insert_action_at_end (buf_t *buf, action_func_t action_func,
+ void *action_arg);
+void buffer_append_action_at_end (buf_t *buf, action_func_t action_func,
+ void *action_arg);
+void buffer_insert_action_at (buf_t *buf, action_func_t action_func,
+ void *action_arg, ogg_int64_t position);
+void buffer_append_action_at (buf_t *buf, action_func_t action_func,
+ void *action_arg, ogg_int64_t position);
+
+/* --- Buffer status functions --- */
+void buffer_wait_for_empty (buf_t *buf);
+long buffer_full (buf_t *buf);
+buffer_stats_t *buffer_statistics (buf_t *buf);
+#endif /* __BUFFER_H__ */
1.14 +13 -9 vorbis-tools/ogg123/ogg123.1
Index: ogg123.1
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.1,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- ogg123.1 2001/08/13 04:40:01 1.13
+++ ogg123.1 2001/12/19 02:52:53 1.14
@@ -14,6 +14,12 @@
.B -k
.I seconds
] [
+.B -x
+.I nth
+] [
+.B -y
+.I ntimes
+] [
.B -b
.I buffer_size
] [
@@ -72,6 +78,13 @@
Display version information.
.IP "-v, --verbose"
Increase verbosity.
+.IP "-x n, --nth"
+Play every 'n'th decoded block. Has the effect of playing audio at 'n' times
+faster than normal speed.
+.IP "-y n, --ntimes"
+Repeat every played block 'n' times. Has the effect of playing audio 'n'
+times slower than normal speed. May be with -x for interesting fractional
+speeds.
.IP "-z, --shuffle"
Play files in pseudo-random order.
@@ -243,15 +256,6 @@
immediately, due to audio data buffering in the audio device.
This delay is system dependent, but it is usually not more
than one or two seconds.
-
-.SH NOTES
-
-The use of
-.B /etc/ogg123rc
-and
-.B ~/.ogg123rc
-has been removed in favor of the configuration system provided by
-libao. The ability to override libao will be added in a future version.
.SH FILES
1.50 +474 -577 vorbis-tools/ogg123/ogg123.c
Index: ogg123.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- ogg123.c 2001/11/28 05:47:16 1.49
+++ ogg123.c 2001/12/19 02:52:54 1.50
@@ -1,5 +1,5 @@
-/* ogg123.c by Kenneth Arnold <kcarnold at arnoldnet.net> */
-/* Modified to use libao by Stan Seibert <volsung at asu.edu> */
+/* ogg123.c by Kenneth Arnold <ogg123 at arnoldnet.net> */
+/* Maintained by Stan Seibert <volsung at xiph.org> */
/********************************************************************
* *
@@ -8,657 +8,554 @@
* THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
* PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2000 *
- * by Monty <monty at xiph.org> and the XIPHOPHORUS Company *
+ * 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: ogg123.c,v 1.49 2001/11/28 05:47:16 volsung Exp $
+ last mod: $Id: ogg123.c,v 1.50 2001/12/19 02:52:54 volsung Exp $
********************************************************************/
-/* FIXME : That was a messy message. Fix it. */
-
#include <sys/types.h>
#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 <signal.h>
+#include "audio.h"
+#include "buffer.h"
+#include "callbacks.h"
+#include "cfgfile_options.h"
+#include "cmdline_options.h"
+#include "format.h"
+#include "transport.h"
+#include "status.h"
+#include "compat.h"
#include "ogg123.h"
+void exit_cleanup ();
+void play (char *source_string);
+
/* take buffer out of the data segment, not the stack */
-char convbuffer[BUFFER_CHUNK_SIZE];
-int convsize = BUFFER_CHUNK_SIZE;
-buf_t * buffer = NULL;
-
-static char skipfile_requested;
-static void (*old_sig)(int);
-
-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"},
- {"TRACKNUMBER=", "Track number: %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}
+#define AUDIO_CHUNK_SIZE 4096
+unsigned char convbuffer[AUDIO_CHUNK_SIZE];
+int convsize = AUDIO_CHUNK_SIZE;
+
+ogg123_options_t options;
+stat_format_t *stat_format;
+buf_t *audio_buffer;
+
+audio_play_arg_t audio_play_arg;
+
+
+/* ------------------------- config file options -------------------------- */
+
+/* This macro is used to create some dummy variables to hold default values
+ for the options. */
+#define INIT(type, value) type type##_##value = value
+char char_n = 'n';
+float float_50f = 50.0f;
+float float_0f = 0.0f;
+INIT(int, 10000);
+INIT(int, 1);
+INIT(int, 0);
+
+file_option_t file_opts[] = {
+ /* found, name, description, type, ptr, default */
+ {0, "default_device", "default output device", opt_type_string,
+ &options.default_device, NULL},
+ {0, "shuffle", "shuffle playlist", opt_type_bool,
+ &options.shuffle, &int_0},
+ {0, "verbose", "verbosity level", opt_type_int,
+ &options.verbosity, &int_1},
+ {0, "outbuffer", "out buffer size (kB)", opt_type_int,
+ &options.buffer_size, &int_0},
+ {0, "outprebuffer", "out prebuffer (%)", opt_type_float,
+ &options.prebuffer, &float_0f},
+ {0, NULL, NULL, 0, NULL, NULL}
};
-struct option long_options[] = {
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
- {"device", required_argument, 0, 'd'},
- {"file", required_argument, 0, 'f'},
- {"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'},
- {"buffer", required_argument, 0, 'b'},
- {"delay", required_argument, 0, 'l'},
- {0, 0, 0, 0}
-};
-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"
- " -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");
-}
+/* Flags set by the signal handler to control the threads */
+signal_request_t sig_request = {0, 0, 0, 0};
-int main(int argc, char **argv)
+
+/* ------------------------------- signal handler ------------------------- */
+
+
+void signal_handler (int signo)
{
- 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;
-
- opt.read_file = NULL;
- opt.shuffle = 0;
- opt.verbose = 0;
- opt.quiet = 0;
- opt.seekpos = 0;
- opt.instream = NULL;
- opt.outdevices = NULL;
- opt.buffer_size = 0;
- opt.delay = 1;
-
- ao_initialize();
-
- while (-1 != (ret = getopt_long(argc, argv, "b:d:f:hl:k:o:qvVz",
- long_options, &option_index))) {
- switch (ret) {
- case 0:
- fprintf(stderr,
- "Internal error: long option given when none expected.\n");
- exit(1);
- case 'b':
- opt.buffer_size = atoi(optarg) / (BUFFER_CHUNK_SIZE / 1024);
- if (opt.buffer_size == 1)
- opt.buffer_size = 0; /* Hack to work around boundary case in
- buffering code. FIXME! */
- break;
- case 'd':
- temp_driver_id = ao_driver_id(optarg);
- if (temp_driver_id < 0) {
- fprintf(stderr, "No such device %s.\n", optarg);
- exit(1);
- }
- current = append_device(opt.outdevices, temp_driver_id,
- NULL, NULL);
- if(opt.outdevices == NULL)
- opt.outdevices = current;
- current_options = ¤t->options;
- break;
- case 'f':
- if (temp_driver_id >= 0) {
- info = ao_driver_info(temp_driver_id);
- if (info->type == AO_TYPE_FILE) {
- free(current->filename);
- current->filename = strdup(optarg);
- } else {
- fprintf(stderr, "Driver %s is not a file output driver.\n",
- info->short_name);
- exit(1);
- }
- } else {
- fprintf(stderr, "Cannot specify output file without specifying a driver.\n");
- exit (1);
- }
- break;
- case 'k':
- opt.seekpos = atof(optarg);
- break;
- case 'l':
- opt.delay = atoi(optarg);
- break;
- case 'o':
- if (optarg && !add_option(current_options, optarg)) {
- fprintf(stderr, "Incorrect option format: %s.\n", optarg);
- exit(1);
- }
- break;
- case 'h':
- usage();
- exit(0);
- case 'q':
- opt.quiet++;
- break;
- case 'v':
- opt.verbose++;
- break;
- case 'V':
- fprintf(stderr, "Ogg123 from " PACKAGE " " VERSION "\n");
- exit(0);
- case 'z':
- opt.shuffle = 1;
- break;
- case '?':
- break;
- default:
- usage();
- exit(1);
- }
- }
+ switch (signo) {
+ case SIGALRM:
+ sig_request.ticks++;
+ if (sig_request.ticks < options.delay) {
+ signal (SIGALRM, signal_handler);
+ alarm(1);
+ }
+ break;
+
+ case SIGINT:
+ if (sig_request.ticks < options.delay)
+ sig_request.exit = 1;
+ else
+ sig_request.skipfile = 1;
+ break;
- /* Use the default device if needed */
- if (temp_driver_id < 0) {
- temp_driver_id = ao_default_driver_id();
-
- if (temp_driver_id < 0) {
- fprintf(stderr,
- "Could not load default driver. Audio devices may be already in use.\nExiting.\n");
- exit(1);
- }
+ case SIGTSTP:
+ sig_request.pause = 1;
+ /* buffer_Pause (Options.outputOpts.buffer);
+ buffer_WaitForPaused (Options.outputOpts.buffer);
+ }
+ if (Options.outputOpts.devicesOpen == 0) {
+ close_audio_devices (Options.outputOpts.devices);
+ Options.outputOpts.devicesOpen = 0;
+ }
+ */
+ /* open_audio_devices();
+ if (Options.outputOpts.buffer) {
+ buffer_Unpause (Options.outputOpts.buffer);
+ }
+ */
+ break;
- opt.outdevices = append_device(opt.outdevices, temp_driver_id,
- temp_options, NULL);
- }
+ case SIGCONT:
+ break; /* Don't need to do anything special to resume */
+ }
+}
- if (optind == argc) {
- usage();
- exit(1);
- }
+/* -------------------------- util functions ---------------------------- */
- if (opt.shuffle) {
- int i;
-
- srand(time(NULL));
+void options_init (ogg123_options_t *opts)
+{
+ opts->verbosity = 1;
+ opts->shuffle = 0;
+ opts->delay = 2;
+ opts->nth = 1;
+ opts->ntimes = 1;
+ opts->seekpos = 0.0;
+ opts->buffer_size = 0;
+ opts->prebuffer = 0.0f;
+ opts->default_device = NULL;
- for (i = optind; i < argc; i++) {
- int j = i + rand() % (argc - i);
- char *temp = argv[i];
- argv[i] = argv[j];
- argv[j] = temp;
- }
- }
+ opts->status_freq = 10.0;
+}
- while (optind < argc) {
- opt.read_file = argv[optind];
- play_file(opt);
- optind++;
- }
- while (opt.outdevices != NULL) {
- if (opt.outdevices->device)
- ao_close(opt.outdevices->device);
- current = opt.outdevices->next_device;
- free(opt.outdevices);
- opt.outdevices = current;
- }
+/* This function selects which statistics to display for our
+ particular configuration. This does not have anything to do with
+ verbosity, but rather with which stats make sense to display. */
+void select_stats (stat_format_t *stats, ogg123_options_t *opts,
+ data_source_t *source, decoder_t *decoder,
+ buf_t *audio_buffer)
+{
+ data_source_stats_t *data_source_stats;
- if (buffer != NULL)
- buffer_shutdown(buffer);
-
- ao_shutdown();
+ if (audio_buffer != NULL) {
+ /* Turn on output buffer stats */
+ stats[8].enabled = 1; /* Fill */
+ stats[9].enabled = 1; /* State */
+ } else {
+ stats[8].enabled = 0;
+ stats[9].enabled = 0;
+ }
- return (0);
+ data_source_stats = source->transport->statistics(source);
+ if (data_source_stats->input_buffer_used) {
+ /* Turn on input buffer stats */
+ stats[6].enabled = 1; /* Fill */
+ stats[7].enabled = 1; /* State */
+ } else {
+ stats[6].enabled = 0;
+ stats[7].enabled = 0;
+ }
+
+ /* Put logic here to decide if this stream needs a total time display */
}
-/* Two signal handlers, one for SIGINT, and the second for
- * SIGALRM. They are de/activated on an as-needed basis by the
- * player to allow the user to stop ogg123 or skip songs.
- */
-void signal_skipfile(int which_signal)
+/* Handles printing statistics depending upon whether or not we have
+ buffering going on */
+void display_statistics (stat_format_t *stat_format,
+ buf_t *audio_buffer,
+ data_source_t *source,
+ decoder_t *decoder)
{
- skipfile_requested = 1;
+ print_statistics_arg_t *pstats_arg;
+ buffer_stats_t *buffer_stats;
+
+ pstats_arg = new_print_statistics_arg(stat_format,
+ source->transport->statistics(source),
+ decoder->format->statistics(decoder));
+
+ /* Disable/Enable statistics as needed */
+
+ if (pstats_arg->decoder_statistics->total_time <
+ pstats_arg->decoder_statistics->current_time) {
+ stat_format[2].enabled = 0; /* Remaining playback time */
+ stat_format[3].enabled = 0; /* Total playback time */
+ }
- /* libao, when writing wav's, traps SIGINT so it correctly
- * closes things down in the event of an interrupt. We
- * honour this. libao will re-raise SIGINT once it cleans
- * up properly, causing the application to exit. This is
- * desired since we would otherwise re-open output.wav
- * and blow away existing "output.wav" file.
- */
-
- if (old_sig != NULL) {
- signal(which_signal,old_sig);
- raise(which_signal);
+ if (pstats_arg->data_source_statistics->input_buffer_used) {
+ stat_format[6].enabled = 1; /* Input buffer fill % */
+ stat_format[7].enabled = 1; /* Input buffer state */
}
+ if (audio_buffer) {
+ /* Place a status update into the buffer */
+ buffer_append_action_at_end(audio_buffer,
+ &print_statistics_action,
+ pstats_arg);
+
+ /* And if we are not playing right now, do an immediate
+ update just the output buffer */
+ buffer_stats = buffer_statistics(audio_buffer);
+ if (buffer_stats->paused || buffer_stats->prebuffering) {
+ pstats_arg = new_print_statistics_arg(stat_format,
+ NULL,
+ NULL);
+ print_statistics_action(audio_buffer, pstats_arg);
+ }
+ free(buffer_stats);
+
+ } else
+ print_statistics_action(NULL, pstats_arg);
}
+
-void signal_activate_skipfile(int ignored)
+void display_statistics_quick (stat_format_t *stat_format,
+ buf_t *audio_buffer,
+ data_source_t *source,
+ decoder_t *decoder)
{
- old_sig = signal(SIGINT,signal_skipfile);
+ print_statistics_arg_t *pstats_arg;
+
+ pstats_arg = new_print_statistics_arg(stat_format,
+ source->transport->statistics(source),
+ decoder->format->statistics(decoder));
+
+ if (audio_buffer) {
+ print_statistics_action(audio_buffer, pstats_arg);
+ } else
+ print_statistics_action(NULL, pstats_arg);
}
-void play_file(ogg123_options_t opt)
+void print_audio_devices_info(audio_device_t *d)
{
- /* Oh my gosh this is disgusting. Big cleanups here will include an
- almost complete rewrite of the hacked-out HTTP streaming and a shift
- to using callbacks for the vorbisfile input.
- */
+ ao_info *info;
- 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);
- }
- /* 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 {
- 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;
- }
+ while (d != NULL) {
+ info = ao_driver_info(d->driver_id);
+
+ status_message(2, "\nDevice: %s", info->name);
+ status_message(2, "Author: %s", info->author);
+ status_message(2, "Comments: %s\n", info->comment);
- if ((ov_open(opt.instream, &vf, NULL, 0)) < 0) {
- fprintf(stderr, "E: input not an Ogg Vorbis audio stream.\n");
- return;
- }
+ d = d->next_device;
+ }
- /* 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) {
- skipfile_requested = 0;
- signal(SIGALRM,signal_activate_skipfile);
- alarm(opt.delay);
- }
+}
- while (!eof) {
- 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, &buffer) < 0)
- exit(1);
-
- 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;
-
- for (i = 0; ogg_comment_keys[i].key != NULL; i++)
- if (!strncasecmp
- (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", cc);
- }
-
- fprintf(stderr, "\nBitstream is %d channel, %ldHz\n",
- vi->channels, vi->rate);
- if (opt.verbose > 1)
- fprintf(stderr, "Encoded by: %s\n\n", vc->vendor);
- }
- 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;
- t_sec = u_time - 60 * t_min;
- }
+/* --------------------------- main code -------------------------------- */
- 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 song */
- realseekpos = ov_time_total(&vf, -1) - 0.01;
-
- if (realseekpos > 0)
- ov_time_seek(&vf, realseekpos);
-
- eos = 0;
-
- while (!eos) {
-
- if (skipfile_requested) {
- eof = eos = 1;
- skipfile_requested = 0;
- signal(SIGALRM,signal_activate_skipfile);
- alarm(opt.delay);
- if (buffer) {
- buffer_flush (buffer);
- }
- break;
- }
-
- old_section = current_section;
- ret =
- ov_read(&vf, convbuffer, sizeof(convbuffer), is_big_endian,
- 2, 1, ¤t_section);
- if (ret == 0) {
- /* End of file */
- eof = eos = 1;
- } else if (ret == OV_HOLE) {
- 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");
- } else if (ret < 0) {
- /* Stream error */
- fprintf(stderr, "Error: libvorbis reported a stream error.\n");
- } else {
- /* did we enter a new logical bitstream */
- if (old_section != current_section && old_section != -1)
- eos = 1;
-
- if (buffer)
- {
- chunk_t chunk;
- chunk.len = ret;
- memcpy (chunk.data, convbuffer, ret);
-
- submit_chunk (buffer, chunk);
- }
- else
- devices_write(convbuffer, ret, opt.outdevices);
-
- if (opt.verbose > 0) {
- if (ov_seekable (&vf)) {
- 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);
- } else {
- /* working around a bug in vorbisfile */
- u_pos = (double) ov_pcm_tell(&vf) / (double) vi->rate;
- c_min = (long) u_pos / (long) 60;
- c_sec = u_pos - 60 * c_min;
- fprintf(stderr,
- "\rTime: %02li:%05.2f, Bitrate: %.1f \r",
- c_min, c_sec,
- (float) ov_bitrate_instant (&vf) / 1000.0F);
- }
- }
- }
- }
- }
- alarm(0);
- signal(SIGALRM,SIG_DFL);
- signal(SIGINT,old_sig);
- ov_clear(&vf);
+int main(int argc, char **argv)
+{
+ int optind;
- if (opt.quiet < 1)
- fprintf(stderr, "\nDone.\n");
-}
+ ao_initialize();
+ stat_format = stat_format_create();
+ options_init(&options);
+ file_options_init(file_opts);
-int get_tcp_socket(void)
-{
- return socket(AF_INET, SOCK_STREAM, 0);
-}
+ parse_std_configs(file_opts);
+ optind = parse_cmdline_options(argc, argv, &options, file_opts);
-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;
- }
+ audio_play_arg.devices = options.devices;
+ audio_play_arg.stat_format = stat_format;
+
+ /* Don't use status_message until after this point! */
+ status_set_verbosity(options.verbosity);
+
+ print_audio_devices_info(options.devices);
- 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;
+ /* Setup signal handlers and callbacks */
+
+ ATEXIT (exit_cleanup);
+ signal (SIGINT, signal_handler);
+ signal (SIGTSTP, signal_handler);
+ signal (SIGCONT, signal_handler);
+ signal (SIGALRM, signal_handler);
+
+ /* Do we have anything left to play? */
+ if (optind == argc) {
+ cmdline_usage();
+ exit(1);
+ }
+
+ /* Setup buffer */
+ if (options.buffer_size > 0) {
+ audio_buffer = buffer_create(options.buffer_size,
+ options.buffer_size * options.prebuffer / 100,
+ audio_play_callback, &audio_play_arg,
+ AUDIO_CHUNK_SIZE);
+ if (audio_buffer == NULL) {
+ status_error("Error: Could not create audio buffer.\n");
+ exit(1);
+ }
+ } else
+ audio_buffer = NULL;
+
+
+ /* Shuffle playlist */
+ if (options.shuffle) {
+ int i;
+
+ srandom(time(NULL));
+
+ for (i = optind; i < argc; i++) {
+ int j = optind + random() % (argc - i);
+ char *temp = argv[i];
+ argv[i] = argv[j];
+ argv[j] = temp;
}
- return fdopen(sockfd, "r+b");
+ }
+
+
+ /* Play the files/streams */
+
+ while (optind < argc) {
+ play(argv[optind]);
+ optind++;
+ }
+
+
+ exit (0);
}
-int open_audio_devices(ogg123_options_t *opt, int rate, int channels, buf_t **buffer)
+
+void play (char *source_string)
{
- static int prevrate=0, prevchan=0;
- devices_t *current;
- ao_sample_format format;
+ transport_t *transport;
+ format_t *format;
+ data_source_t *source;
+ decoder_t *decoder;
+
+ decoder_callbacks_t decoder_callbacks;
+ void *decoder_callbacks_arg;
+
+ /* Preserve between calls so we only open the audio device when we
+ have to */
+ static audio_format_t old_audio_fmt = { 0, 0, 0, 0, 0 };
+ audio_format_t new_audio_fmt;
+ audio_reopen_arg_t *reopen_arg;
+
+ /* Flags and counters galore */
+ int eof = 0, eos = 0, ret;
+ int nthc = 0, ntimesc = 0;
+ int next_status = 0;
+ int status_interval = 0;
+
+
+ /* Set preferred audio format (used by decoder) */
+ new_audio_fmt.big_endian = ao_is_big_endian();
+ new_audio_fmt.signed_sample = 1;
+ new_audio_fmt.word_size = 2;
+
+ /* Select appropriate callbacks */
+ if (audio_buffer != NULL) {
+ decoder_callbacks.printf_error = &decoder_buffered_error_callback;
+ decoder_callbacks.printf_metadata = &decoder_buffered_error_callback;
+ decoder_callbacks_arg = audio_buffer;
+ } else {
+ decoder_callbacks.printf_error = &decoder_error_callback;
+ decoder_callbacks.printf_metadata = &decoder_error_callback;
+ decoder_callbacks_arg = NULL;
+ }
- if(prevrate == rate && prevchan == channels)
- return 0;
+ /* Locate and use transport for this data source */
+ if ( (transport = select_transport(source_string)) == NULL ) {
+ status_error("No module could be found to read from %s.\n", source_string);
+ return;
+ }
- if(prevrate !=0 && prevchan!=0)
- {
- if (buffer != NULL && *buffer != NULL) {
- buffer_shutdown (*buffer);
- *buffer = NULL;
- }
-
- current = opt->outdevices;
- while (current != NULL) {
- ao_close(current->device);
- current = current->next_device;
- }
- }
+ if ( (source = transport->open(source_string, &options)) == NULL ) {
+ status_error("Cannot open %s.\n", source_string);
+ return;
+ }
+
+ /* Detect the file format and initialize a decoder */
+ if ( (format = select_format(source)) == NULL ) {
+ status_error("The file format of %s is not supported.\n", source_string);
+ return;
+ }
- format.rate = prevrate = rate;
- format.channels = prevchan = channels;
- format.bits = 16;
- format.byte_format = AO_FMT_NATIVE;
-
- current = opt->outdevices;
- while (current != NULL) {
- ao_info *info = ao_driver_info(current->driver_id);
-
- 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);
- fprintf(stderr, "\n");
- }
+ if ( (decoder = format->init(source, &options, &new_audio_fmt,
+ &decoder_callbacks, audio_buffer)) == NULL ) {
+ status_error("Error opening %s using the %s module."
+ " The file may be corrupted.\n", source_string,
+ format->name);
+ return;
+ }
+
+ /* Decide which statistics are valid */
+ select_stats(stat_format, &options, source, decoder, audio_buffer);
+
+
+ /* Reset all of the signal flags and setup the timer */
+ sig_request.skipfile = 0;
+ sig_request.exit = 0;
+ sig_request.pause = 0;
+ sig_request.ticks = 0;
+ alarm(1); /* Count seconds */
+
+
+ /* Start the audio playback thread before we begin sending data */
+ if (audio_buffer != NULL) {
- if (current->filename == NULL)
- current->device = ao_open_live(current->driver_id, &format,
- current->options);
- else
- current->device = ao_open_file(current->driver_id, current->filename,
- 1, &format, current->options);
+ /* First reset mutexes and other synchronization variables */
+ buffer_reset (audio_buffer);
+ buffer_thread_start (audio_buffer);
+ }
- if (current->device == NULL) {
- switch (errno) {
- case AO_ENODRIVER:
- fprintf(stderr, "Error: No device not available.\n");
- break;
- case AO_ENOTLIVE:
- fprintf(stderr, "Error: %s requires an output filename to be specified with -f.\n", info->short_name);
- break;
- case AO_EBADOPTION:
- fprintf(stderr, "Error: Unsupported option value to %s device.\n",
- info->short_name);
- break;
- case AO_EOPENDEVICE:
- fprintf(stderr, "Error: Cannot open device %s.\n",
- info->short_name);
- break;
- case AO_EFAIL:
- fprintf(stderr, "Error: Device failure.\n");
- break;
- case AO_ENOTFILE:
- fprintf(stderr, "Error: An output file cannot be given for %s device.\n", info->short_name);
- break;
- case AO_EOPENFILE:
- fprintf(stderr, "Error: Cannot open file %s for writing.\n",
- current->filename);
+ /* Skip over audio */
+ if (options.seekpos > 0.0) {
+ if (!format->seek(decoder, options.seekpos, DECODER_SEEK_START))
+ status_error("Could not skip %f seconds of audio.", options.seekpos);
+ }
+
+ /* Main loop: Iterates over all of the logical bitstreams in the file */
+ while (!eof && !sig_request.exit) {
+
+ /* Loop through data within a logical bitstream */
+ eos = 0;
+ while (!eos && !sig_request.exit) {
+
+ /* Check signals */
+ if (sig_request.skipfile) {
+ eof = eos = 1;
break;
- case AO_EFILEEXISTS:
- fprintf(stderr, "Error: File %s already exists.\n", current->filename);
+ }
+
+ if (sig_request.pause) {
+ if (audio_buffer)
+ buffer_thread_pause (audio_buffer);
+
+ kill (getpid(), SIGSTOP); /* We block here until we unpause */
+
+ /* Done pausing */
+ if (audio_buffer)
+ buffer_thread_unpause (audio_buffer);
+
+ sig_request.pause = 0;
+ }
+
+
+ /* Read another block of audio data */
+ ret = format->read(decoder, convbuffer, convsize, &eos, &new_audio_fmt);
+
+ /* Bail if we need to */
+ if (ret == 0) {
+ eof = eos = 1;
break;
- default:
- fprintf(stderr, "Error: This error should never happen. Panic!\n");
+ } else if (ret < 0) {
+ status_error("Error: Decoding failure.\n");
break;
}
+
+
+ /* Check to see if the audio format has changed */
+ if (!audio_format_equal(&new_audio_fmt, &old_audio_fmt)) {
+ old_audio_fmt = new_audio_fmt;
+
+ /* Update our status printing interval */
+ status_interval = new_audio_fmt.word_size * new_audio_fmt.channels *
+ new_audio_fmt.rate / options.status_freq;
+ next_status = 0;
+
+ reopen_arg = new_audio_reopen_arg(options.devices, &new_audio_fmt);
+
+ if (audio_buffer)
+ buffer_insert_action_at_end(audio_buffer, &audio_reopen_action,
+ reopen_arg);
+ else
+ audio_reopen_action(NULL, reopen_arg);
+ }
+
+
+ /* Update statistics display if needed */
+ if (next_status <= 0) {
+ display_statistics(stat_format, audio_buffer, source, decoder);
+ next_status = status_interval;
+ } else
+ next_status -= ret;
+
+
+ /* Write audio data block to output, skipping or repeating chunks
+ as needed */
+ do {
- return -1;
+ if (nthc-- == 0) {
+ if (audio_buffer)
+ buffer_submit_data(audio_buffer, convbuffer, ret);
+ else
+ audio_play_callback(convbuffer, ret, eos, &audio_play_arg);
+
+ nthc = options.nth - 1;
+ }
+
+ } while (++ntimesc < options.ntimes);
+
+ ntimesc = 0;
+
+ } /* End of data loop */
+
+ } /* End of logical bitstream loop */
+
+ /* Done playing this logical bitstream. Clean up house. */
+
+ if (audio_buffer) {
+
+ if (!sig_request.exit && !sig_request.skipfile) {
+ buffer_mark_eos(audio_buffer);
+ buffer_wait_for_empty(audio_buffer);
}
- current = current->next_device;
+
+ buffer_thread_kill(audio_buffer);
}
+
+ /* Print final stats */
+ display_statistics_quick(stat_format, audio_buffer, source, decoder);
+
- if (opt->buffer_size)
- *buffer = fork_writer (opt->buffer_size, opt->outdevices);
+ alarm(0);
+ format->cleanup(decoder);
+ transport->close(source);
+ status_reset_output_lock(); /* In case we were killed mid-output */
+
+ status_message(1, "Done.");
- return 0;
+ if (sig_request.exit)
+ exit (0);
+}
+
+
+void exit_cleanup ()
+{
+
+ if (audio_buffer != NULL) {
+ buffer_destroy (audio_buffer);
+ audio_buffer = NULL;
+ }
+
+ ao_onexit (options.devices);
}
1.10 +46 -48 vorbis-tools/ogg123/ogg123.h
Index: ogg123.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- ogg123.h 2001/08/12 14:04:21 1.9
+++ ogg123.h 2001/12/19 02:52:54 1.10
@@ -1,51 +1,49 @@
-/* This file is part of ogg123, an Ogg Vorbis player. See ogg123.c
- * for copyright information. */
-#ifndef __OGG123_H
-#define __OGG123_H
-
-/* Common includes */
-#include <ogg/ogg.h>
-#include <vorbis/codec.h>
-#include <vorbis/vorbisfile.h>
-#include <ao/ao.h>
-
-#ifdef __sun
-#include <alloca.h>
-#endif
-
-/* For facilitating output to multiple devices */
-typedef struct devices_s {
- int driver_id;
- ao_device *device;
- ao_option *options;
- char *filename;
- 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. */
- int buffer_size; /* Size of the buffer in chunks. */
- int rate, channels; /* playback params for opening audio devices */
- int delay; /* delay for skip to next song */
-} ogg123_options_t; /* Changed in 0.6 to be non-static */
+/********************************************************************
+ * *
+ * 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: ogg123.h,v 1.10 2001/12/19 02:52:54 volsung Exp $
+
+ ********************************************************************/
+
+#ifndef __OGG123_H__
+#define __OGG123_H__
+
+#include <ogg/os_types.h>
+#include "audio.h"
-/* This goes here because it relies on some of the above. */
-#include "buffer.h"
+typedef struct ogg123_options_t {
+ long int verbosity; /* Verbose output if > 1, quiet if 0 */
-devices_t *append_device(devices_t * devices_list, int driver_id,
- ao_option * options, char *filename);
-void devices_write(void *ptr, size_t size, devices_t * d);
-void usage(void);
-int add_option(ao_option ** op_h, const char *optstring);
-void play_file(ogg123_options_t opt);
-int get_tcp_socket(void); /* Will be going soon. */
-FILE *http_open(char *server, int port, char *path); /* ditto */
-int open_audio_devices(ogg123_options_t *opt, int rate, int channels, buf_t ** buffer);
+ int shuffle; /* Should we shuffle playing? */
+ int delay; /* delay for skip to next song */
+ int nth; /* Play every nth chunk */
+ int ntimes; /* Play every chunk n times */
+ double seekpos; /* Position in file to seek to */
+
+ long buffer_size; /* Size of audio buffer */
+ float prebuffer; /* Percent of buffer to fill before playing */
+ char *default_device; /* Name of default driver to use */
+
+ audio_device_t *devices; /* Audio devices to use */
+
+ double status_freq; /* Number of status updates per second */
+} ogg123_options_t;
+
+typedef struct signal_request_t {
+ int skipfile;
+ int exit;
+ int pause;
+ ogg_int64_t ticks;
+} signal_request_t;
-#endif /* !defined(__OGG123_H) */
+#endif /* __OGG123_H__ */
1.4 +15 -2 vorbis-tools/ogg123/ogg123rc-example
Index: ogg123rc-example
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogg123/ogg123rc-example,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ogg123rc-example 2001/06/18 02:29:16 1.3
+++ ogg123rc-example 2001/12/19 02:52:54 1.4
@@ -1,3 +1,16 @@
-# Copy this to ~/.ogg123rc and edit as necessary. The current
-# parser appears to handle comments.
+# Copy this to ~/.ogg123rc and edit as necessary. These are all the
+# default options except for default device, which is a reasonable
+# default for many people. To see a full list of available options,
+# type:
+#
+# $ ogg123 -c
+
default_device=oss
+shuffle=n
+verbose=1
+outbuffer=0
+outprebuffer=0
+inbuffer=10000
+inprebuffer=10
+#save_stream=
+delay=1
1.2 +127 -0 vorbis-tools/ogg123/audio.c
1.2 +56 -0 vorbis-tools/ogg123/audio.h
1.2 +360 -0 vorbis-tools/ogg123/callbacks.c
1.2 +72 -0 vorbis-tools/ogg123/callbacks.h
1.2 +454 -0 vorbis-tools/ogg123/cfgfile_options.c
1.2 +59 -0 vorbis-tools/ogg123/cfgfile_options.h
1.2 +276 -0 vorbis-tools/ogg123/cmdline_options.c
1.2 +31 -0 vorbis-tools/ogg123/cmdline_options.h
1.2 +37 -0 vorbis-tools/ogg123/compat.h
1.2 +161 -0 vorbis-tools/ogg123/file_transport.c
1.2 +65 -0 vorbis-tools/ogg123/format.c
1.2 +78 -0 vorbis-tools/ogg123/format.h
1.2 +298 -0 vorbis-tools/ogg123/http_transport.c
1.2 +380 -0 vorbis-tools/ogg123/oggvorbis_format.c
1.2 +460 -0 vorbis-tools/ogg123/status.c
1.2 +74 -0 vorbis-tools/ogg123/status.h
1.2 +65 -0 vorbis-tools/ogg123/transport.c
1.2 +62 -0 vorbis-tools/ogg123/transport.h
1.12 +1 -1 vorbis-tools/oggenc/Makefile.am
Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/oggenc/Makefile.am,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- Makefile.am 2001/09/22 22:49:50 1.11
+++ Makefile.am 2001/12/19 02:52:58 1.12
@@ -6,7 +6,7 @@
bin_PROGRAMS = oggenc
-INCLUDES = @OGG_CFLAGS@ @VORBIS_CFLAGS@ -I$(top_srcdir)/include
+INCLUDES = @OGG_CFLAGS@ @VORBIS_CFLAGS@ @SHARE_CFLAGS@
oggenc_LDADD = @VORBISENC_LIBS@ @VORBIS_LIBS@ @OGG_LIBS@ @LIBICONV@ \
@SHARE_LIBS@
1.6 +1 -1 vorbis-tools/ogginfo/Makefile.am
Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/ogginfo/Makefile.am,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- Makefile.am 2001/09/22 22:49:50 1.5
+++ Makefile.am 2001/12/19 02:52:58 1.6
@@ -6,7 +6,7 @@
mandir = @MANDIR@
man_MANS = ogginfo.1
-INCLUDES = @OGG_CFLAGS@ @VORBIS_CFLAGS@
+INCLUDES = @OGG_CFLAGS@ @VORBIS_CFLAGS@ @SHARE_CFLAGS@
ogginfo_LDADD = @VORBIS_LIBS@ @OGG_LIBS@ @LIBICONV@ @SHARE_LIBS@
ogginfo_DEPENDENCIES = @SHARE_LIBS@
1.4 +2 -2 vorbis-tools/share/Makefile.am
Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/share/Makefile.am,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- Makefile.am 2001/10/02 03:03:42 1.3
+++ Makefile.am 2001/12/19 02:52:58 1.4
@@ -6,11 +6,11 @@
noinst_LIBRARIES = libutf8.a libgetopt.a
-libutf8_a_SOURCES = charset.c iconvert.c utf8.c
+libutf8_a_SOURCES = charset.c charset.h iconvert.c utf8.c
libgetopt_a_SOURCES = getopt.c getopt1.c
-EXTRA_DIST = charmaps.h makemap.c charset_test.c
+EXTRA_DIST = charmaps.h makemap.c charset_test.c charsetmap.h
debug:
$(MAKE) all CFLAGS="@DEBUG@"
1.4 +1 -1 vorbis-tools/vcut/vcut.c
Index: vcut.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/vcut/vcut.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- vcut.c 2001/07/16 13:09:57 1.3
+++ vcut.c 2001/12/19 02:52:59 1.4
@@ -7,7 +7,7 @@
* Simple application to cut an ogg at a specified frame, and produce two
* output files.
*
- * last modified: $Id: vcut.c,v 1.3 2001/07/16 13:09:57 msmith Exp $
+ * last modified: $Id: vcut.c,v 1.4 2001/12/19 02:52:59 volsung Exp $
*/
#include <stdio.h>
1.10 +1 -1 vorbis-tools/vorbiscomment/Makefile.am
Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/vorbiscomment/Makefile.am,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- Makefile.am 2001/09/22 22:49:52 1.9
+++ Makefile.am 2001/12/19 02:52:59 1.10
@@ -4,7 +4,7 @@
bin_PROGRAMS = vorbiscomment
-INCLUDES = @OGG_CFLAGS@ @VORBIS_CFLAGS@ -I$(top_srcdir)/include
+INCLUDES = @OGG_CFLAGS@ @VORBIS_CFLAGS@ @SHARE_CFLAGS@
vorbiscomment_LDADD = @VORBIS_LIBS@ @OGG_LIBS@ @LIBICONV@ @SHARE_LIBS@
vorbiscomment_DEPENDENCIES = @SHARE_LIBS@
1.16 +1 -1 vorbis-tools/vorbiscomment/vcedit.c
Index: vcedit.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis-tools/vorbiscomment/vcedit.c,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- vcedit.c 2001/11/07 12:45:03 1.15
+++ vcedit.c 2001/12/19 02:53:00 1.16
@@ -6,7 +6,7 @@
*
* Comment editing backend, suitable for use by nice frontend interfaces.
*
- * last modified: $Id: vcedit.c,v 1.15 2001/11/07 12:45:03 msmith Exp $
+ * last modified: $Id: vcedit.c,v 1.16 2001/12/19 02:53:00 volsung Exp $
*/
#include <stdio.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