[xiph-cvs] cvs commit: ao/src/plugins/alsa09 Makefile.am ao_alsa09.c

Stan Seibert volsung at xiph.org
Fri Aug 31 09:10:33 PDT 2001



volsung     01/08/31 09:10:33

  Modified:    .        configure.in
               src      ao_private.h
               src/plugins Makefile.am
  Added:       src/plugins/alsa09 Makefile.am ao_alsa09.c
  Log:
  Adds the ALSA 0.9.x plugin contributed by Bill Currie <bill at taniwha.org>.

Revision  Changes    Path
1.31      +21 -2     ao/configure.in

Index: configure.in
===================================================================
RCS file: /usr/local/cvsroot/ao/configure.in,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- configure.in	2001/08/22 01:56:24	1.30
+++ configure.in	2001/08/31 16:10:31	1.31
@@ -149,7 +149,7 @@
 AC_CHECK_HEADERS(machine/soundcard.h)
 AM_CONDITIONAL(HAVE_OSS,test "${ac_cv_header_sys_soundcard_h}" = "yes" || test "${ac_cv_header_machine_soundcard_h}" = "yes")
 
-dnl Check for ALSA
+dnl Check for ALSA 0.5.x
 
 AC_ARG_ENABLE(alsa, [  --enable-alsa           include alsa 0.5 output plugin ],
 [ BUILD_ALSA="$enableval" ],[ BUILD_ALSA="yes" ])
@@ -167,6 +167,24 @@
 fi
 AC_SUBST(ALSA_LIBS)
 
+dnl Check for ALSA 0.9.x
+
+AC_ARG_ENABLE(alsa09, [  --enable-alsa09           include alsa 0.9 output plugin ],
+[ BUILD_ALSA09="$enableval" ],[ BUILD_ALSA09="yes" ])
+
+if test "$BUILD_ALSA" = "yes"; then
+   AC_CHECK_LIB(asound, snd_pcm_open, have_alsa09=yes, have_alsa09=no)
+   AC_CHECK_HEADER(sys/asoundlib.h, , have_alsa09=no)
+   AM_CONDITIONAL(HAVE_ALSA09,test "x$have_alsa09" = xyes)
+fi
+
+if test "x$have_alsa09" = xyes; then
+	ALSA09_LIBS="-lasound"
+else
+	ALSA09_LIBS=""
+fi
+AC_SUBST(ALSA09_LIBS)
+
 dnl Check for Sun audio
 
 AC_CHECK_HEADERS(sys/audioio.h)
@@ -201,5 +219,6 @@
 AM_CONDITIONAL(HAVE_IRIX,test "x$have_irix" = xyes)
 
 AM_CONDITIONAL(HAVE_SOLARIS,test "x$have_solaris" = xyes)
+
+AC_OUTPUT(Makefile src/Makefile doc/Makefile include/Makefile include/ao/Makefile include/ao/os_types.h src/plugins/Makefile src/plugins/esd/Makefile src/plugins/oss/Makefile src/plugins/alsa/Makefile src/plugins/alsa09/Makefile src/plugins/sun/Makefile src/plugins/irix/Makefile src/plugins/arts/Makefile debian/Makefile)
 
-AC_OUTPUT(Makefile src/Makefile doc/Makefile include/Makefile include/ao/Makefile include/ao/os_types.h src/plugins/Makefile src/plugins/esd/Makefile src/plugins/oss/Makefile src/plugins/alsa/Makefile src/plugins/sun/Makefile src/plugins/irix/Makefile src/plugins/arts/Makefile debian/Makefile)

1.4       +1 -1      ao/src/ao_private.h

Index: ao_private.h
===================================================================
RCS file: /usr/local/cvsroot/ao/src/ao_private.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ao_private.h	2001/08/13 05:24:04	1.3
+++ ao_private.h	2001/08/31 16:10:32	1.4
@@ -42,7 +42,7 @@
 #if defined(__OpenBSD__)	
 #define DLOPEN_FLAG RTLD_LAZY
 #else
-#define DLOPEN_FLAG RTLD_NOW
+#define DLOPEN_FLAG (RTLD_NOW | RTLD_GLOBAL)
 #endif
 
 /* --- Constants --- */

1.5       +1 -1      ao/src/plugins/Makefile.am

Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/ao/src/plugins/Makefile.am,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- Makefile.am	2001/08/04 02:56:15	1.4
+++ Makefile.am	2001/08/31 16:10:32	1.5
@@ -1,4 +1,4 @@
 ## Process this file with automake to produce Makefile.in
 
 AUTOMAKE_OPTIONS = foreign
-SUBDIRS = oss esd arts alsa sun irix # macosx
+SUBDIRS = oss esd arts alsa alsa09 sun irix # macosx

1.1                  ao/src/plugins/alsa09/Makefile.am

Index: Makefile.am
===================================================================
## Process this file with automake to produce Makefile.in

AUTOMAKE_OPTIONS = foreign

if HAVE_ALSA09

alsa09ltlibs = libalsa09.la
alsa09ldflags = -export-dynamic -avoid-version
alsa09sources = ao_alsa09.c

else

alsa09ltlibs =
alsa09ldflags =
alsa09sources =

endif

INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include

libdir = $(plugindir)
lib_LTLIBRARIES = $(alsa09ltlibs)

libalsa09_la_LDFLAGS = $(alsa09ldflags)
libalsa09_la_LIBADD = @ALSA09_LIBS@
libalsa09_la_SOURCES = $(alsa09sources)

EXTRA_DIST = ao_alsa09.c

1.1                  ao/src/plugins/alsa09/ao_alsa09.c

Index: ao_alsa09.c
===================================================================
/*
 *
 *  ao_alsa09.c
 *
 *      Copyright (C) Stan Seibert - July 2000, July 2001
 *
 *  This file is part of libao, a cross-platform library.  See
 *  README for a history of this source code.
 *
 *  libao is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  libao is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>

#include <sys/asoundlib.h>
#include <ao/ao.h>
#include <ao/plugin.h>

#define AO_ALSA_BUF_SIZE 32768

tatic char *ao_alsa_options[] = {
        "dev",
        "buf_size"
};
static ao_info ao_alsa_info =
{
        AO_TYPE_LIVE,
        "Advanced Linux Sound Architecture (ALSA) output",
        "alsa09",
        "Bill Currie <bill at taniwha.org>",
        "Outputs to the Advanced Linux Sound Architecture version 0.9.x.",
        AO_FMT_NATIVE,
        30,
        ao_alsa_options,
        2
};

typedef struct ao_alsa_internal
{
        snd_pcm_t *pcm_handle;
        char *buf;
        int buf_size;
        int buf_end;
        int sample_size;
        char *dev;
} ao_alsa_internal;

int ao_plugin_test()
{
        snd_pcm_t *handle;
        int err;

        err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK,
                           SND_PCM_NONBLOCK);

        if (err != 0)
                return 0; /* Cannot use this plugin with default parameters */
        else {
                snd_pcm_close(handle);
                return 1; /* This plugin works in default mode */
        }
}

ao_info *ao_plugin_driver_info(void)
{
        return &ao_alsa_info;
}

int ao_plugin_device_init(ao_device *device)
{
        ao_alsa_internal *internal;

        internal = (ao_alsa_internal *) malloc(sizeof(ao_alsa_internal));

        if (internal == NULL)	
                return 0; /* Could not initialize device memory */
        
        internal->buf_size = AO_ALSA_BUF_SIZE;
        internal->dev = strdup ("default");
        if (!internal->dev) {
                free (internal);
                return 0;
        }
        
        device->internal = internal;

        return 1; /* Memory alloc successful */
}

int ao_plugin_set_option(ao_device *device, const char *key, const char *value)
{
        ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;

        if (!strcmp(key, "dev")) {
                if (internal->dev)
                        free (internal->dev);
                internal->dev = strdup (value);
                if (!internal->dev)
                        return 0;
        }
        else if (!strcmp(key, "buf_size"))
                internal->buf_size = atoi(value);

        return 1;
}

int ao_plugin_open(ao_device *device, ao_sample_format *format)
{
        ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;
        snd_pcm_hw_params_t *hwparams;

        int err;
        int fmt;
        char *cmd;

        internal->buf = malloc(internal->buf_size);
        internal->buf_end = 0;
        if (internal->buf == NULL)
          return 0;  /* Could not alloc swap buffer */

        /* Open the ALSA device */
        err = snd_pcm_open(&(internal->pcm_handle), internal->dev,
                        SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
        if (err < 0) {
                free (internal->buf);
                return 0;
        }

        snd_pcm_hw_params_alloca(&hwparams);

        cmd = "snd_pcm_hw_params_any";
        err = snd_pcm_hw_params_any(internal->pcm_handle, hwparams);
        if (err < 0)
                goto error;

        cmd = "snd_pcm_hw_params_set_access";
        err = snd_pcm_hw_params_set_access(internal->pcm_handle, hwparams,
                        SND_PCM_ACCESS_RW_INTERLEAVED);
        if (err < 0)
                goto error;

        switch (format->bits) {
        case 8  : fmt = SND_PCM_FORMAT_S8;
                  break;
        case 16 : fmt = 
                  device->client_byte_format == AO_FMT_BIG ?
                  SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE;
                  device->driver_byte_format = device->client_byte_format;
                  break;
        default : return 0;
        }
        cmd = "snd_pcm_hw_params_set_format";
        err = snd_pcm_hw_params_set_format(internal->pcm_handle, hwparams, fmt);
        if (err < 0)
                goto error;

        cmd = "snd_pcm_hw_params_set_channels";
        if (format->channels == 1 || format->channels == 2)
                err = snd_pcm_hw_params_set_channels(internal->pcm_handle,
                                hwparams, format->channels);
        else
                return 0;
        if (err < 0)
                goto error;
        internal->sample_size = format->bits * format->channels / 8;

        cmd = "snd_pcm_hw_params_set_rate";
        err = snd_pcm_hw_params_set_rate_near(internal->pcm_handle, hwparams,
                        format->rate, 0);
        if (err < 0)
                goto error;

        cmd = "snd_pcm_hw_params_set_period_size";
        err = snd_pcm_hw_params_set_period_size(internal->pcm_handle, hwparams,
                        internal->buf_size / internal->sample_size, 0);
        if (err < 0)
                goto error;

        cmd = "snd_pcm_hw_params_set_periods";
        err = snd_pcm_hw_params_set_periods(internal->pcm_handle, hwparams,
                        2, 0);
        if (err < 0)
                goto error;

        cmd = "snd_pcm_hw_params";
        err = snd_pcm_hw_params(internal->pcm_handle, hwparams);
        if (err < 0)
                goto error;

        cmd = "snd_pcm_prepare";
        err = snd_pcm_prepare(internal->pcm_handle);
        if (err < 0)
                goto error;

        return 1;
error:
        fprintf(stderr, "ALSA %s error: %s\n", cmd, snd_strerror(err));
        snd_pcm_close(internal->pcm_handle);
        free(internal->buf);
        return 0;
}

int _alsa_write_buffer(ao_alsa_internal *s)
{
        snd_pcm_t *pcm_handle = s->pcm_handle;
        int len = s->buf_end / s->sample_size;
        int err;
        char *buf = s->buf;

        s->buf_end = 0;

        do {
                err = snd_pcm_writei (pcm_handle, buf, len);
                if (err == -EAGAIN)
                        snd_pcm_wait (pcm_handle, 1000);
        } while (err == -EAGAIN);
        if (err == -EPIPE) {
                /* fprintf(stderr, "ALSA: underrun. resetting stream\n"); */
                snd_pcm_prepare(pcm_handle);
                err = snd_pcm_writei(pcm_handle, buf, len);
                if (err != len) {
                        fprintf(stderr, "ALSA write error: %s\n", snd_strerror(err));
                        return 0;
                } else if (err < 0) {
                        fprintf(stderr, "ALSA write error: %s\n", snd_strerror(err));
                        return 0;
                }
        }

        return 1;
}	

int ao_plugin_play(ao_device *device, const char *output_samples, 
                uint_32 num_bytes)
{
        ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;
        
        int packed = 0;
        int copy_len;
        char *samples = (char *) output_samples;
        int ok = 1;

        while (packed < num_bytes && ok) {
                /* Pack the buffer */
                if (num_bytes-packed < internal->buf_size - internal->buf_end)
                        copy_len = num_bytes - packed;
                else
                        copy_len = internal->buf_size - internal->buf_end;

                memcpy(internal->buf + internal->buf_end, samples + packed, 
                       copy_len); 
                packed += copy_len;
                internal->buf_end += copy_len;

                if(internal->buf_end == internal->buf_size)
                        ok = _alsa_write_buffer(internal);
        }

        return ok;
}

int ao_plugin_close(ao_device *device)
{
        ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;
        int result;

        /* Clear buffer */
        result = _alsa_write_buffer(internal);
        snd_pcm_close(internal->pcm_handle);
        free(internal->buf);

        return result;
}

void ao_plugin_device_clear(ao_device *device)
{
        ao_alsa_internal *internal = (ao_alsa_internal *) device->internal;
        if (internal->dev)
                free (internal->dev);
        free(internal);
}

--- >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