Commit 7ef99b09 authored by Stan Seibert's avatar Stan Seibert

Finally, we merge my branch onto the head. Duck and cover.

svn path=/trunk/vorbis-tools/; revision=2838
parent 016e0ba3
......@@ -28,7 +28,7 @@ AC_ARG_ENABLE(oggtest, [ --disable-oggtest Do not try to compile and run
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 @@ int main ()
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@icecast.org> 10-21-2000
# Shamelessly stolen from Owen Taylor and Manish Singh
......@@ -472,3 +410,293 @@ AC_DEFUN([AM_LANGINFO_CODESET],
[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@alum.mit.edu> and
dnl Alejandro Forero Cuervo <bachue@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
])
......@@ -19,12 +19,6 @@ CFLAGS="$cflags_save"
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
......@@ -81,18 +75,6 @@ DEBUG="$DEBUG $cflags_save"
PROFILE="$PROFILE $cflags_save"
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 --------------------------------------------------
......@@ -100,17 +82,23 @@ 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 @@ dnl --------------------------------------------------
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)
......@@ -8,15 +8,20 @@ doc_DATA = ogg123rc-example
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)
......
/********************************************************************
* *
* 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@arnoldnet.net> AND OTHER CONTRIBUTORS *
* http://www.xiph.org/ *
* *
********************************************************************
last mod: $Id: audio.c,v 1.2 2001/12/19 02:52:53 volsung Exp $
********************************************************************/
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include "audio.h"
int audio_format_equal (audio_format_t *a, audio_format_t *b)
{
return
a->big_endian == b->big_endian &&
a->word_size == b->word_size &&
a->signed_sample == b->signed_sample &&
a->rate == b->rate &&
a->channels == b->channels;
}
audio_device_t *append_audio_device(audio_device_t *devices_list,
int driver_id,
ao_option *options, char *filename)
{
audio_device_t *head = devices_list;
if (devices_list != NULL) {
while (devices_list->next_device != NULL)
devices_list = devices_list->next_device;
devices_list = devices_list->next_device =
malloc(sizeof(audio_device_t));
} else {
head = devices_list = (audio_device_t *) malloc(sizeof(audio_device_t));
}
devices_list->driver_id = driver_id;
devices_list->options = options;
devices_list->filename = filename;
devices_list->device = NULL;
devices_list->next_device = NULL;
return devices_list;
}
int audio_devices_write(audio_device_t *d, void *ptr, int nbytes)
{
while (d != NULL) {
if (ao_play(d->device, ptr, nbytes) == 0)
return 0; /* error occurred */
d = d->next_device;
}
return 1;
}
int add_ao_option(ao_option **op_h, const char *optstring)
{
char *key, *value;
int result;
key = strdup(optstring);
if (key == NULL)
return 0;
value = strchr(key, ':');
if (value == NULL) {
free(key);
return 0;
}
/* split by replacing the separator with a null */
*value++ = '\0';
result = ao_append_option(op_h, key, value);
free(key);
return (result);
}
void close_audio_devices (audio_device_t *devices)
{
audio_device_t *current = devices;
while (current != NULL) {
if (current->device)
ao_close(current->device);
current->device = NULL;
current = current->next_device;
}
}
void free_audio_devices (audio_device_t *devices)
{
audio_device_t *current;
while (devices != NULL) {
current = devices->next_device;
free (devices);
devices = current;
}
}
void ao_onexit (void *arg)
{
audio_device_t *devices = (audio_device_t *) arg;
close_audio_devices (devices);
free_audio_devices (devices);
ao_shutdown();
}
/********************************************************************
* *
* 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@arnoldnet.net> AND OTHER CONTRIBUTORS *
* http://www.xiph.org/ *
* *
********************************************************************
last mod: $Id: audio.h,v 1.2 2001/12/19 02:52:53 volsung Exp $
********************************************************************/
/* ogg123's audio playback functions */
#ifndef __AUDIO_H__
#define __AUDIO_H__
#include <ao/ao.h>
typedef struct audio_format_t {
int big_endian;
int word_size;
int signed_sample;
int rate;
int channels;
} audio_format_t;
/* For facilitating output to multiple devices */
typedef struct audio_device_t {
int driver_id;
ao_device *device;
ao_option *options;
char *filename;
struct audio_device_t *next_device;
} audio_device_t;
int audio_format_equal (audio_format_t *a, audio_format_t *b);
audio_device_t *append_audio_device(audio_device_t *devices_list,
int driver_id,
ao_option *options, char *filename);
void audio_devices_print_info(audio_device_t *d);
int audio_devices_write(audio_device_t *d, void *ptr, int nbytes);
int add_ao_option(ao_option **op_h, const char *optstring);
void close_audio_devices (audio_device_t *devices);
void free_audio_devices (audio_device_t *devices);
void ao_onexit (void *arg);
#endif /* __AUDIO_H__ */
/* 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@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"
/* Initialize the buffer structure. */
void buffer_init (buf_t *buf, long size)
#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 ------------------ *