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

hpuxsndcard.c

/*
  The mediastreamer library aims at providing modular media processing and I/O
      for linphone, but also for any telephony application.
  Copyright (C) 2001  Simon MORLAT simon.morlat@linphone.org
                                                            
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library 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
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "sndcard.h"
#include "osscard.h"

#ifdef HAVE_SYS_AUDIO_H
#include <sys/audio.h>


#include "mssndread.h"
#include "mssndwrite.h"

#include <errno.h>
#include <fcntl.h>


int hpuxsnd_open(HpuxSndCard *obj, int bits,int stereo, int rate)
{
      int fd;
      int p=0,cond=0;
      int i=0;
      int min_size=0,blocksize=512;
      /* do a quick non blocking open to be sure that we are not going to be blocked here
            for the eternity */
      fd=open(obj->dev_name,O_RDWR|O_NONBLOCK);
      if (fd<0) return -EWOULDBLOCK;
      close(fd);
      /* open the device */
      fd=open(obj->dev_name,O_RDWR);

      g_return_val_if_fail(fd>0,-errno);

      ioctl(fd,AUDIO_RESET,0);
      ioctl(fd,AUDIO_SET_SAMPLE_RATE,rate);
      ioctl(fd,AUDIO_SET_CHANNELS,stereo);
      p=AUDIO_FORMAT_LINEAR16BIT;
      ioctl(fd,AUDIO_SET_DATA_FORMAT,p); 
      /* ioctl(fd,AUDIO_GET_RXBUFSIZE,&min_size); does not work ? */
      min_size=2048;

      g_message("dsp blocksize is %i.",min_size);
      obj->fd=fd;
      obj->readpos=0;
      obj->writepos=0;
      SND_CARD(obj)->bits=bits;
      SND_CARD(obj)->stereo=stereo;
      SND_CARD(obj)->rate=rate;
      SND_CARD(obj)->bsize=min_size;
      return fd;
}

int hpux_snd_card_probe(HpuxSndCard *obj,int bits,int stereo,int rate)
{
      return 2048;
}


int hpux_snd_card_open(HpuxSndCard *obj,int bits,int stereo,int rate)
{
      int fd;
      obj->ref++;
      if (obj->fd==0){
            fd=hpuxsnd_open(obj,bits,stereo,rate);
            if (fd<0) {
                  obj->fd=0;
                  obj->ref--;
                  return -1;
            }
      }
      SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED;
      return 0;
}

void hpux_snd_card_close(HpuxSndCard *obj)
{
      int i;
      obj->ref--;
      if (obj->ref==0) {
            close(obj->fd);
            obj->fd=0;
            SND_CARD(obj)->flags&=~SND_CARD_FLAGS_OPENED;
            
      }
}

void hpux_snd_card_destroy(HpuxSndCard *obj)
{
      snd_card_uninit(SND_CARD(obj));
      g_free(obj->dev_name);
      g_free(obj->mixdev_name);
}

gboolean hpux_snd_card_can_read(HpuxSndCard *obj)
{
      struct timeval tout={0,0};
      int err;
      fd_set fdset;
      FD_ZERO(&fdset);
      FD_SET(obj->fd,&fdset);
      err=select(obj->fd+1,&fdset,NULL,NULL,&tout);
      if (err>0) return TRUE;
      else return FALSE;
}

int hpux_snd_card_read(HpuxSndCard *obj,char *buf,int size)
{
      int err;
      gint bsize=SND_CARD(obj)->bsize;
      if (size<bsize){
            gint canread=MIN(bsize-obj->readpos,size);
            if (obj->readbuf==NULL) obj->readbuf=g_malloc0(bsize);
            if (obj->readpos==0){
                  err=read(obj->fd,obj->readbuf,bsize);
                  if (err<0) {
                        g_warning("hpux_snd_card_read: read() failed:%s.",strerror(errno));
                        return -1;
                  }
            }
                  
            memcpy(buf,&obj->readbuf[obj->readpos],canread);
            obj->readpos+=canread;
            if (obj->readpos>=bsize) obj->readpos=0;
            return canread;
      }else{
            err=read(obj->fd,buf,size);
            if (err<0) {
                  g_warning("hpux_snd_card_read: read-2() failed:%s.",strerror(errno));
            }
            return err;
      }
      
}

int hpux_snd_card_write(HpuxSndCard *obj,char *buf,int size)
{
      int err;
      gint bsize=SND_CARD(obj)->bsize;
      if (size<bsize){
            gint canwrite=MIN(bsize-obj->writepos,size);
            if (obj->writebuf==NULL) obj->writebuf=g_malloc0(bsize);
            
            memcpy(&obj->writebuf[obj->writepos],buf,canwrite);
            obj->writepos+=canwrite;
            if (obj->writepos>=bsize){
                  err=write(obj->fd,obj->writebuf,bsize);
            }
            return canwrite;
      }else{
            return write(obj->fd,buf,bsize);
      }
}

#define SND_CARD_LEVEL_TO_HPUX_LEVEL(a)    (((a)*2) - 100)
#define HPUX_LEVEL_TO_SND_CARD_LEVEL(a)         (((a)+200)/2)
void hpux_snd_card_set_level(HpuxSndCard *obj,gint way,gint a)
{
      struct audio_gain gain;
      int error,mix_fd;
            
      g_return_if_fail(obj->mixdev_name!=NULL);
      memset(&gain,0,sizeof(struct audio_gain));
      switch(way){
            case SND_CARD_LEVEL_GENERAL:
                  gain.cgain[0].monitor_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a);
                  gain.cgain[1].monitor_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a);
            break;
            case SND_CARD_LEVEL_INPUT:
                  gain.cgain[0].receive_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a);
                  gain.cgain[1].receive_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a);
            break;
            case SND_CARD_LEVEL_OUTPUT:
                  gain.cgain[0].transmit_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a);
                  gain.cgain[1].transmit_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a);
            break;
            default:
                  g_warning("hpux_snd_card_set_level: unsupported command.");
                  return;
      }
      gain.channel_mask=AUDIO_CHANNEL_RIGHT|AUDIO_CHANNEL_LEFT;
      mix_fd = open(obj->mixdev_name, O_WRONLY);
      g_return_if_fail(mix_fd>0);
      error=ioctl(mix_fd,AUDIO_SET_GAINS,&gain);
      if (error<0){
      g_warning("hpux_snd_card_set_level: Could not set gains: %s",strerror(errno));
      }
      close(mix_fd);
}

gint hpux_snd_card_get_level(HpuxSndCard *obj,gint way)
{
      struct audio_gain gain;
      int p=0,mix_fd,error;
      g_return_if_fail(obj->mixdev_name!=NULL);
      
      gain.channel_mask=AUDIO_CHANNEL_RIGHT|AUDIO_CHANNEL_LEFT;
      mix_fd = open(obj->mixdev_name, O_RDONLY);
      g_return_if_fail(mix_fd>0);
      error=ioctl(mix_fd,AUDIO_GET_GAINS,&gain);
      if (error<0){
      g_warning("hpux_snd_card_set_level: Could not get gains: %s",strerror(errno));
      }
      close(mix_fd);
      
      switch(way){
            case SND_CARD_LEVEL_GENERAL:
                  p=gain.cgain[0].monitor_gain;
            break;
            case SND_CARD_LEVEL_INPUT:
                  p=gain.cgain[0].receive_gain;
            break;
            case SND_CARD_LEVEL_OUTPUT:
                  p=gain.cgain[0].transmit_gain;
            break;
            default:
                  g_warning("hpux_snd_card_get_level: unsupported command.");
                  return -1;
      }
      return HPUX_LEVEL_TO_SND_CARD_LEVEL(p);
}

void hpux_snd_card_set_source(HpuxSndCard *obj,int source)
{
      gint p=0;
      gint mix_fd;
      gint error=0;
      g_return_if_fail(obj->mixdev_name!=NULL);
      
      mix_fd=open("/dev/audio",O_WRONLY);
      g_return_if_fail(mix_fd>0);
      switch(source){
            case 'm':
                  error=ioctl(mix_fd,AUDIO_SET_INPUT,AUDIO_IN_MIKE);
            break;
            case 'l':
                  error=ioctl(mix_fd,AUDIO_SET_INPUT,AUDIO_IN_LINE);
            break;
            default:
                  g_warning("hpux_snd_card_set_source: unsupported source.");
      }
      close(mix_fd);
}

MSFilter *hpux_snd_card_create_read_filter(HpuxSndCard *card)
{
      MSFilter *f=ms_snd_read_new();
      ms_snd_read_set_device(MS_SND_READ(f),SND_CARD(card)->index);
      return f;
}

MSFilter *hpux_snd_card_create_write_filter(HpuxSndCard *card)
{
      MSFilter *f=ms_snd_write_new();
      ms_snd_write_set_device(MS_SND_WRITE(f),SND_CARD(card)->index);
      return f;
}


SndCard * hpux_snd_card_new(char *devname, char *mixdev_name)
{
      HpuxSndCard * obj= g_new0(HpuxSndCard,1);
      SndCard *base= SND_CARD(obj);
      snd_card_init(base);
      obj->dev_name=g_strdup(devname);
      obj->mixdev_name=g_strdup( mixdev_name);
      base->card_name=g_strdup(devname);
      base->_probe=(SndCardOpenFunc)hpux_snd_card_probe;
      base->_open_r=(SndCardOpenFunc)hpux_snd_card_open;
      base->_open_w=(SndCardOpenFunc)hpux_snd_card_open;
      base->_can_read=(SndCardPollFunc)hpux_snd_card_can_read;
      base->_read=(SndCardIOFunc)hpux_snd_card_read;
      base->_write=(SndCardIOFunc)hpux_snd_card_write;
      base->_close_r=(SndCardCloseFunc)hpux_snd_card_close;
      base->_close_w=(SndCardCloseFunc)hpux_snd_card_close;
      base->_set_rec_source=(SndCardMixerSetRecSourceFunc)hpux_snd_card_set_source;
      base->_set_level=(SndCardMixerSetLevelFunc)hpux_snd_card_set_level;
      base->_get_level=(SndCardMixerGetLevelFunc)hpux_snd_card_get_level;
      base->_destroy=(SndCardDestroyFunc)hpux_snd_card_destroy;
      base->_create_read_filter=(SndCardCreateFilterFunc)hpux_snd_card_create_read_filter;
      base->_create_write_filter=(SndCardCreateFilterFunc)hpux_snd_card_create_write_filter;
      return base;
}

#endif

Generated by  Doxygen 1.6.0   Back to index