Logo Search packages:      
Sourcecode: vat version File versions  Download package

audio-bsd.cc

/*
 * Copyright (c) 1991-1993 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    This product includes software developed by the Computer Systems
 *    Engineering Group at Lawrence Berkeley Laboratory.
 * 4. Neither the name of the University nor of the Laboratory may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
static const char rcsid[] =
    "@(#) $Header: audio-bsd.cc,v 1.16 96/03/16 13:12:46 van Exp $ (LBL)";

#include "audio-sun.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#ifdef sun
#include <sbusdev/bsd_audioio.h>
#else
#include <machine/audioio.h>
#endif

class BSDAudio : public SUNAudio {
    public:
      inline BSDAudio(const char* device) : SUNAudio(device) {}
      virtual int FrameReady();
      virtual u_char* Read();
      virtual void Obtain();
      virtual void Catchup(int);
      virtual int RDrops();
      virtual int AdjustTime(u_int);
      virtual void Flush();
      virtual int CanFilter() const { return 1; }
      virtual int outputs() const;
    protected:
      virtual int setinfo(struct audio_info*);
      virtual int getinfo(struct audio_info*);
};

static class BSDAudioMatcher : public Matcher {
public:
      BSDAudioMatcher() : Matcher("audio") {}
      TclObject* match(const char* id) {
            if (strcasecmp(id, "bsd") == 0) {
                  Tcl& tcl = Tcl::instance();
                  const char* device = tcl.attr("audioFileName");
                  int i = -1;;
                  if (strcmp(device, "/dev/audio") == 0 &&
                      (i = open("/dev/audioctl", O_RDONLY, 0)) < 0)
                        return (new BSDAudio(device));
                  (void)close(i);
            }
            return (0);
      }
} bsdaudio_matcher;

void BSDAudio::Obtain()
{
      if (HaveAudio())
            abort();

      fd = open(device_, O_RDWR|O_NDELAY);
      if (fd >= 0) {
            int on = 1;
            ioctl(fd, FIONBIO, (char*)&on);
            audio_info_t* i = (audio_info_t*)state;
            AUDIO_INITINFO((audio_info_t*)state);
            i->blocksize = blksize;
            i->record.gain = rgain;
            i->play.gain = pgain;
            i->play.port = oport? AUDIO_HEADPHONE :
            AUDIO_SPEAKER;
            setinfo(i);
            /* flush input to get rid of any data fragments */
            Flush();
            Audio::Obtain();
      }
}

u_char* BSDAudio::Read()
{
      u_char* cp = buf;
      register int len = blksize;
      int cc = read(fd, (char *)cp, len);
      if ((len -= cc) != 0) {
            do {
                  if (cc < 0) {
                        switch (errno) {
                        case EINVAL:
                              /* probably wrapped file pos. */
                              lseek(fd, 0, SEEK_SET);
                              break;

                        case EPERM:
                              /* probably lost audio */
                              break;

                        default:
                              perror("audio read");
                              break;
                        }
                        break;
                  }
                  cp += cc;
                  cc = read(fd, (char *)cp, len);
                  len -= cc;
            } while (len > 0);
      }
      return (buf);
}

int BSDAudio::FrameReady()
{
      return (1);
}

void BSDAudio::Catchup(int)
{
      /* XXX This should happen only with a very busy system. */
      printf("trying to catch up!\n");
      exit(1);
}

int BSDAudio::RDrops()
{
      int n;
      if (fd < 0 || ioctl(fd, AUDIO_RERROR, (char *)&n) < 0)
            n = -1;
      return (n);
}

int BSDAudio::getinfo(audio_info_t* info)
{
      int sts;
      if (fd < 0)
            sts = 0;
      else
            sts = ioctl(fd, AUDIO_GETINFO, (char*)info);
      return (sts);
}

int BSDAudio::setinfo(audio_info_t* info)
{
      int sts;
      if (fd < 0)
            sts = 0;
      else
            sts = ioctl(fd, AUDIO_SETINFO, (char*)info);
      return (sts);
}

/*
 * The time difference betwee now and when the audio last write
 * actually happens (i.e., when the last write actually starts
 * being output by the kernel).
 */
int BSDAudio::AdjustTime(u_int now)
{
      u_long stamp;
      if (ioctl(fd, AUDIO_WSEEK, (char *)&stamp) < 0) {
            perror("AUDIO_WSEEK");
            return (0);
      }
      return (stamp - now);
}

void BSDAudio::Flush()
{
      if (ioctl(fd, AUDIO_FLUSH, (char *)0) < 0) {
            perror("AUDIO_FLUSH");
            exit(1);
      }
}

int BSDAudio::outputs() const
{
      return (2);
}

Generated by  Doxygen 1.6.0   Back to index