| 1 /* |
|
| 2 The mediastreamer library aims at providing modular media processing and I/O |
|
| 3 for linphone, but also for any telephony application. |
|
| 4 Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org |
|
| 5 |
|
| 6 This library is free software; you can redistribute it and/or |
|
| 7 modify it under the terms of the GNU Lesser General Public |
|
| 8 License as published by the Free Software Foundation; either |
|
| 9 version 2.1 of the License, or (at your option) any later version. |
|
| 10 |
|
| 11 This library is distributed in the hope that it will be useful, |
|
| 12 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
| 14 Lesser General Public License for more details. |
|
| 15 |
|
| 16 You should have received a copy of the GNU Lesser General Public |
|
| 17 License along with this library; if not, write to the Free Software |
|
| 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
| 19 */ |
|
| 20 |
|
| 21 #include "sndcard.h" |
|
| 22 #include "osscard.h" |
|
| 23 |
|
| 24 #ifdef HAVE_SYS_AUDIO_H |
|
| 25 #include <sys/audio.h> |
|
| 26 |
|
| 27 |
|
| 28 #include "msossread.h" |
|
| 29 #include "msosswrite.h" |
|
| 30 |
|
| 31 #include <errno.h> |
|
| 32 #include <fcntl.h> |
|
| 33 |
|
| 34 |
|
| 35 int hpuxsnd_open(HpuxSndCard *obj, int bits,int stereo, int rate) |
|
| 36 { |
|
| 37 int fd; |
|
| 38 int p=0,cond=0; |
|
| 39 int i=0; |
|
| 40 int min_size=0,blocksize=512; |
|
| 41 /* do a quick non blocking open to be sure that we are not going to be blocked here |
|
| 42 for the eternity */ |
|
| 43 fd=open(obj->dev_name,O_RDWR|O_NONBLOCK); |
|
| 44 if (fd<0) return -EWOULDBLOCK; |
|
| 45 close(fd); |
|
| 46 /* open the device */ |
|
| 47 fd=open(obj->dev_name,O_RDWR); |
|
| 48 |
|
| 49 g_return_val_if_fail(fd>0,-errno); |
|
| 50 |
|
| 51 ioctl(fd,AUDIO_RESET,0); |
|
| 52 ioctl(fd,AUDIO_SET_SAMPLE_RATE,rate); |
|
| 53 ioctl(fd,AUDIO_SET_CHANNELS,stereo); |
|
| 54 p=AUDIO_FORMAT_LINEAR16BIT; |
|
| 55 ioctl(fd,AUDIO_SET_DATA_FORMAT,p); |
|
| 56 /* ioctl(fd,AUDIO_GET_RXBUFSIZE,&min_size); does not work ? */ |
|
| 57 min_size=2048; |
|
| 58 |
|
| 59 g_message("dsp blocksize is %i.",min_size); |
|
| 60 obj->fd=fd; |
|
| 61 obj->readpos=0; |
|
| 62 obj->writepos=0; |
|
| 63 SND_CARD(obj)->bits=bits; |
|
| 64 SND_CARD(obj)->stereo=stereo; |
|
| 65 SND_CARD(obj)->rate=rate; |
|
| 66 SND_CARD(obj)->bsize=min_size; |
|
| 67 return fd; |
|
| 68 } |
|
| 69 |
|
| 70 int hpux_snd_card_probe(HpuxSndCard *obj,int bits,int stereo,int rate) |
|
| 71 { |
|
| 72 return 2048; |
|
| 73 } |
|
| 74 |
|
| 75 |
|
| 76 int hpux_snd_card_open(HpuxSndCard *obj,int bits,int stereo,int rate) |
|
| 77 { |
|
| 78 int fd; |
|
| 79 obj->ref++; |
|
| 80 if (obj->fd==0){ |
|
| 81 fd=hpuxsnd_open(obj,bits,stereo,rate); |
|
| 82 if (fd<0) { |
|
| 83 obj->fd=0; |
|
| 84 obj->ref--; |
|
| 85 return -1; |
|
| 86 } |
|
| 87 } |
|
| 88 SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED; |
|
| 89 return 0; |
|
| 90 } |
|
| 91 |
|
| 92 void hpux_snd_card_close(HpuxSndCard *obj) |
|
| 93 { |
|
| 94 int i; |
|
| 95 obj->ref--; |
|
| 96 if (obj->ref==0) { |
|
| 97 close(obj->fd); |
|
| 98 obj->fd=0; |
|
| 99 SND_CARD(obj)->flags&=~SND_CARD_FLAGS_OPENED; |
|
| 100 |
|
| 101 } |
|
| 102 } |
|
| 103 |
|
| 104 void hpux_snd_card_destroy(HpuxSndCard *obj) |
|
| 105 { |
|
| 106 snd_card_uninit(SND_CARD(obj)); |
|
| 107 g_free(obj->dev_name); |
|
| 108 g_free(obj->mixdev_name); |
|
| 109 } |
|
| 110 |
|
| 111 gboolean hpux_snd_card_can_read(HpuxSndCard *obj) |
|
| 112 { |
|
| 113 struct timeval tout={0,0}; |
|
| 114 int err; |
|
| 115 fd_set fdset; |
|
| 116 FD_ZERO(&fdset); |
|
| 117 FD_SET(obj->fd,&fdset); |
|
| 118 err=select(obj->fd+1,&fdset,NULL,NULL,&tout); |
|
| 119 if (err>0) return TRUE; |
|
| 120 else return FALSE; |
|
| 121 } |
|
| 122 |
|
| 123 int hpux_snd_card_read(HpuxSndCard *obj,char *buf,int size) |
|
| 124 { |
|
| 125 int err; |
|
| 126 gint bsize=SND_CARD(obj)->bsize; |
|
| 127 if (size<bsize){ |
|
| 128 gint canread=MIN(bsize-obj->readpos,size); |
|
| 129 if (obj->readbuf==NULL) obj->readbuf=g_malloc0(bsize); |
|
| 130 if (obj->readpos==0){ |
|
| 131 err=read(obj->fd,obj->readbuf,bsize); |
|
| 132 if (err<0) { |
|
| 133 g_warning("hpux_snd_card_read: read() failed:%s.",strerror(errno)); |
|
| 134 return -1; |
|
| 135 } |
|
| 136 } |
|
| 137 |
|
| 138 memcpy(buf,&obj->readbuf[obj->readpos],canread); |
|
| 139 obj->readpos+=canread; |
|
| 140 if (obj->readpos>=bsize) obj->readpos=0; |
|
| 141 return canread; |
|
| 142 }else{ |
|
| 143 err=read(obj->fd,buf,size); |
|
| 144 if (err<0) { |
|
| 145 g_warning("hpux_snd_card_read: read-2() failed:%s.",strerror(errno)); |
|
| 146 } |
|
| 147 return err; |
|
| 148 } |
|
| 149 |
|
| 150 } |
|
| 151 |
|
| 152 int hpux_snd_card_write(HpuxSndCard *obj,char *buf,int size) |
|
| 153 { |
|
| 154 int err; |
|
| 155 gint bsize=SND_CARD(obj)->bsize; |
|
| 156 if (size<bsize){ |
|
| 157 gint canwrite=MIN(bsize-obj->writepos,size); |
|
| 158 if (obj->writebuf==NULL) obj->writebuf=g_malloc0(bsize); |
|
| 159 |
|
| 160 memcpy(&obj->writebuf[obj->writepos],buf,canwrite); |
|
| 161 obj->writepos+=canwrite; |
|
| 162 if (obj->writepos>=bsize){ |
|
| 163 err=write(obj->fd,obj->writebuf,bsize); |
|
| 164 } |
|
| 165 return canwrite; |
|
| 166 }else{ |
|
| 167 return write(obj->fd,buf,bsize); |
|
| 168 } |
|
| 169 } |
|
| 170 |
|
| 171 #define SND_CARD_LEVEL_TO_HPUX_LEVEL(a) (((a)*2) - 100) |
|
| 172 #define HPUX_LEVEL_TO_SND_CARD_LEVEL(a) (((a)+200)/2) |
|
| 173 void hpux_snd_card_set_level(HpuxSndCard *obj,gint way,gint a) |
|
| 174 { |
|
| 175 struct audio_gain gain; |
|
| 176 int error,mix_fd; |
|
| 177 |
|
| 178 g_return_if_fail(obj->mixdev_name!=NULL); |
|
| 179 memset(&gain,0,sizeof(struct audio_gain)); |
|
| 180 switch(way){ |
|
| 181 case SND_CARD_LEVEL_GENERAL: |
|
| 182 gain.cgain[0].monitor_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a); |
|
| 183 gain.cgain[1].monitor_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a); |
|
| 184 break; |
|
| 185 case SND_CARD_LEVEL_INPUT: |
|
| 186 gain.cgain[0].receive_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a); |
|
| 187 gain.cgain[1].receive_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a); |
|
| 188 break; |
|
| 189 case SND_CARD_LEVEL_OUTPUT: |
|
| 190 gain.cgain[0].transmit_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a); |
|
| 191 gain.cgain[1].transmit_gain=SND_CARD_LEVEL_TO_HPUX_LEVEL(a); |
|
| 192 break; |
|
| 193 default: |
|
| 194 g_warning("hpux_snd_card_set_level: unsupported command."); |
|
| 195 return; |
|
| 196 } |
|
| 197 gain.channel_mask=AUDIO_CHANNEL_RIGHT|AUDIO_CHANNEL_LEFT; |
|
| 198 mix_fd = open(obj->mixdev_name, O_WRONLY); |
|
| 199 g_return_if_fail(mix_fd>0); |
|
| 200 error=ioctl(mix_fd,AUDIO_SET_GAINS,&gain); |
|
| 201 if (error<0){ |
|
| 202 g_warning("hpux_snd_card_set_level: Could not set gains: %s",strerror(errno)); |
|
| 203 } |
|
| 204 close(mix_fd); |
|
| 205 } |
|
| 206 |
|
| 207 gint hpux_snd_card_get_level(HpuxSndCard *obj,gint way) |
|
| 208 { |
|
| 209 struct audio_gain gain; |
|
| 210 int p=0,mix_fd,error; |
|
| 211 g_return_if_fail(obj->mixdev_name!=NULL); |
|
| 212 |
|
| 213 gain.channel_mask=AUDIO_CHANNEL_RIGHT|AUDIO_CHANNEL_LEFT; |
|
| 214 mix_fd = open(obj->mixdev_name, O_RDONLY); |
|
| 215 g_return_if_fail(mix_fd>0); |
|
| 216 error=ioctl(mix_fd,AUDIO_GET_GAINS,&gain); |
|
| 217 if (error<0){ |
|
| 218 g_warning("hpux_snd_card_set_level: Could not get gains: %s",strerror(errno)); |
|
| 219 } |
|
| 220 close(mix_fd); |
|
| 221 |
|
| 222 switch(way){ |
|
| 223 case SND_CARD_LEVEL_GENERAL: |
|
| 224 p=gain.cgain[0].monitor_gain; |
|
| 225 break; |
|
| 226 case SND_CARD_LEVEL_INPUT: |
|
| 227 p=gain.cgain[0].receive_gain; |
|
| 228 break; |
|
| 229 case SND_CARD_LEVEL_OUTPUT: |
|
| 230 p=gain.cgain[0].transmit_gain; |
|
| 231 break; |
|
| 232 default: |
|
| 233 g_warning("hpux_snd_card_get_level: unsupported command."); |
|
| 234 return -1; |
|
| 235 } |
|
| 236 return HPUX_LEVEL_TO_SND_CARD_LEVEL(p); |
|
| 237 } |
|
| 238 |
|
| 239 void hpux_snd_card_set_source(HpuxSndCard *obj,int source) |
|
| 240 { |
|
| 241 gint p=0; |
|
| 242 gint mix_fd; |
|
| 243 gint error=0; |
|
| 244 g_return_if_fail(obj->mixdev_name!=NULL); |
|
| 245 |
|
| 246 mix_fd=open("/dev/audio",O_WRONLY); |
|
| 247 g_return_if_fail(mix_fd>0); |
|
| 248 switch(source){ |
|
| 249 case 'm': |
|
| 250 error=ioctl(mix_fd,AUDIO_SET_INPUT,AUDIO_IN_MIKE); |
|
| 251 break; |
|
| 252 case 'l': |
|
| 253 error=ioctl(mix_fd,AUDIO_SET_INPUT,AUDIO_IN_LINE); |
|
| 254 break; |
|
| 255 default: |
|
| 256 g_warning("hpux_snd_card_set_source: unsupported source."); |
|
| 257 } |
|
| 258 close(mix_fd); |
|
| 259 } |
|
| 260 |
|
| 261 MSFilter *hpux_snd_card_create_read_filter(HpuxSndCard *card) |
|
| 262 { |
|
| 263 MSFilter *f=ms_oss_read_new(); |
|
| 264 ms_oss_read_set_device(MS_OSS_READ(f),SND_CARD(card)->index); |
|
| 265 return f; |
|
| 266 } |
|
| 267 |
|
| 268 MSFilter *hpux_snd_card_create_write_filter(HpuxSndCard *card) |
|
| 269 { |
|
| 270 MSFilter *f=ms_oss_write_new(); |
|
| 271 ms_oss_write_set_device(MS_OSS_WRITE(f),SND_CARD(card)->index); |
|
| 272 return f; |
|
| 273 } |
|
| 274 |
|
| 275 |
|
| 276 SndCard * hpux_snd_card_new(char *devname, char *mixdev_name) |
|
| 277 { |
|
| 278 HpuxSndCard * obj= g_new0(HpuxSndCard,1); |
|
| 279 SndCard *base= SND_CARD(obj); |
|
| 280 snd_card_init(base); |
|
| 281 obj->dev_name=g_strdup(devname); |
|
| 282 obj->mixdev_name=g_strdup( mixdev_name); |
|
| 283 base->card_name=g_strdup(devname); |
|
| 284 base->_probe=(SndCardOpenFunc)hpux_snd_card_probe; |
|
| 285 base->_open_r=(SndCardOpenFunc)hpux_snd_card_open; |
|
| 286 base->_open_w=(SndCardOpenFunc)hpux_snd_card_open; |
|
| 287 base->_can_read=(SndCardPollFunc)hpux_snd_card_can_read; |
|
| 288 base->_read=(SndCardIOFunc)hpux_snd_card_read; |
|
| 289 base->_write=(SndCardIOFunc)hpux_snd_card_write; |
|
| 290 base->_close_r=(SndCardCloseFunc)hpux_snd_card_close; |
|
| 291 base->_close_w=(SndCardCloseFunc)hpux_snd_card_close; |
|
| 292 base->_set_rec_source=(SndCardMixerSetRecSourceFunc)hpux_snd_card_set_source; |
|
| 293 base->_set_level=(SndCardMixerSetLevelFunc)hpux_snd_card_set_level; |
|
| 294 base->_get_level=(SndCardMixerGetLevelFunc)hpux_snd_card_get_level; |
|
| 295 base->_destroy=(SndCardDestroyFunc)hpux_snd_card_destroy; |
|
| 296 base->_create_read_filter=(SndCardCreateFilterFunc)hpux_snd_card_create_read_filter; |
|
| 297 base->_create_write_filter=(SndCardCreateFilterFunc)hpux_snd_card_create_write_filter; |
|
| 298 return base; |
|
| 299 } |
|
| 300 |
|
| 301 #endif |
|