summaryrefslogtreecommitdiffstats
path: root/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/osscard.c
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitbcb704366cb5e333a626c18c308c7e0448a8e69f (patch)
treef0d6ab7d78ecdd9207cf46536376b44b91a1ca71 /kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/osscard.c
downloadtdenetwork-bcb704366cb5e333a626c18c308c7e0448a8e69f.tar.gz
tdenetwork-bcb704366cb5e333a626c18c308c7e0448a8e69f.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdenetwork@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/osscard.c')
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/osscard.c495
1 files changed, 495 insertions, 0 deletions
diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/osscard.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/osscard.c
new file mode 100644
index 00000000..636c5792
--- /dev/null
+++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/osscard.c
@@ -0,0 +1,495 @@
+/*
+ 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 "osscard.h"
+
+#include "msossread.h"
+#include "msosswrite.h"
+
+#ifdef HAVE_SYS_SOUNDCARD_H
+#include <sys/soundcard.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/time.h>
+
+#if 0
+void * oss_thread(OssCard *obj)
+{
+ gint i;
+ gint err;
+ g_message("oss_thread: starting **********");
+ while(1){
+ for(i=0;i<OSS_CARD_BUFFERS;i++){
+ g_mutex_lock(obj->lock);
+ if (obj->ref==0){
+ g_cond_signal(obj->cond);
+ g_mutex_unlock(obj->lock);
+ g_thread_exit(NULL);
+ }
+ g_mutex_unlock(obj->lock);
+ obj->readindex=i;
+
+ err=read(obj->fd,obj->readbuf[i],SND_CARD(obj)->bsize);
+ if (err<0) g_warning("oss_thread: read() error:%s.",strerror(errno));
+ obj->writeindex=i;
+ write(obj->fd,obj->writebuf[i],SND_CARD(obj)->bsize);
+ memset(obj->writebuf[i],0,SND_CARD(obj)->bsize);
+ }
+ }
+}
+#endif
+int oss_open(OssCard *obj, int bits,int stereo, int rate)
+{
+ int fd;
+ int p=0,cond=0;
+ int i=0;
+ int min_size=0,blocksize=512;
+ int err;
+
+ //g_message("opening sound device");
+ fd=open(obj->dev_name,O_RDWR|O_NONBLOCK);
+ if (fd<0) return -EWOULDBLOCK;
+ /* unset nonblocking mode */
+ /* We wanted non blocking open but now put it back to normal ; thanks Xine !*/
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
+
+ /* reset is maybe not needed but takes time*/
+ /*ioctl(fd, SNDCTL_DSP_RESET, 0); */
+
+
+#ifdef WORDS_BIGENDIAN
+ p=AFMT_U16_BE;
+#else
+ p=AFMT_U16_LE;
+#endif
+
+ err=ioctl(fd,SNDCTL_DSP_SETFMT,&p);
+ if (err<0){
+ g_warning("oss_open: can't set sample format:%s.",strerror(errno));
+ }
+
+
+ p = bits; /* 16 bits */
+ err=ioctl(fd, SNDCTL_DSP_SAMPLESIZE, &p);
+ if (err<0){
+ g_warning("oss_open: can't set sample size to %i:%s.",bits,strerror(errno));
+ }
+
+ p = rate; /* rate in khz*/
+ err=ioctl(fd, SNDCTL_DSP_SPEED, &p);
+ if (err<0){
+ g_warning("oss_open: can't set sample rate to %i:%s.",rate,strerror(errno));
+ }
+
+ p = stereo; /* stereo or not */
+ err=ioctl(fd, SNDCTL_DSP_STEREO, &p);
+ if (err<0){
+ g_warning("oss_open: can't set mono/stereo mode:%s.",strerror(errno));
+ }
+
+ if (rate==16000) blocksize=4096; /* oss emulation is not very good at 16khz */
+ else blocksize=blocksize*(rate/8000);
+ ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &min_size);
+
+ /* try to subdivide BLKSIZE to reach blocksize if necessary */
+ if (min_size>blocksize)
+ {
+ cond=1;
+ p=min_size/blocksize;
+ while(cond)
+ {
+ i=ioctl(fd, SNDCTL_DSP_SUBDIVIDE, &p);
+ //printf("SUB_DIVIDE said error=%i,errno=%i\n",i,errno);
+ if ((i==0) || (p==1)) cond=0;
+ else p=p/2;
+ }
+ }
+ ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &min_size);
+ if (min_size>blocksize)
+ {
+ g_warning("dsp block size set to %i.",min_size);
+ }else{
+ /* no need to access the card with less latency than needed*/
+ min_size=blocksize;
+ }
+
+ g_message("dsp blocksize is %i.",min_size);
+
+ /* start recording !!! Alex */
+ {
+ int fl,res;
+
+ fl=PCM_ENABLE_OUTPUT|PCM_ENABLE_INPUT;
+ res=ioctl(fd, SNDCTL_DSP_SETTRIGGER, &fl);
+ if (res<0) g_warning("OSS_TRIGGER: %s",strerror(errno));
+ }
+
+ 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 oss_card_probe(OssCard *obj,int bits,int stereo,int rate)
+{
+
+ int fd;
+ int p=0,cond=0;
+ int i=0;
+ int min_size=0,blocksize=512;
+
+ if (obj->fd>0) return SND_CARD(obj)->bsize;
+ fd=open(obj->dev_name,O_RDWR|O_NONBLOCK);
+ if (fd<0) {
+ g_warning("oss_card_probe: can't open %s: %s.",obj->dev_name,strerror(errno));
+ return -1;
+ }
+ ioctl(fd, SNDCTL_DSP_RESET, 0);
+
+ p = bits; /* 16 bits */
+ ioctl(fd, SNDCTL_DSP_SAMPLESIZE, &p);
+
+ p = stereo; /* number of channels */
+ ioctl(fd, SNDCTL_DSP_CHANNELS, &p);
+
+ p = rate; /* rate in khz*/
+ ioctl(fd, SNDCTL_DSP_SPEED, &p);
+
+ ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &min_size);
+
+ /* try to subdivide BLKSIZE to reach blocksize if necessary */
+ if (min_size>blocksize)
+ {
+ cond=1;
+ p=min_size/blocksize;
+ while(cond)
+ {
+ i=ioctl(fd, SNDCTL_DSP_SUBDIVIDE, &p);
+ //printf("SUB_DIVIDE said error=%i,errno=%i\n",i,errno);
+ if ((i==0) || (p==1)) cond=0;
+ else p=p/2;
+ }
+ }
+ ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &min_size);
+ if (min_size>blocksize)
+ {
+ g_warning("dsp block size set to %i.",min_size);
+ }else{
+ /* no need to access the card with less latency than needed*/
+ min_size=blocksize;
+ }
+ close(fd);
+ return min_size;
+}
+
+
+int oss_card_open(OssCard *obj,int bits,int stereo,int rate)
+{
+ int fd;
+ obj->ref++;
+ if (obj->fd==0){
+ fd=oss_open(obj,bits,stereo,rate);
+ if (fd<0) {
+ obj->fd=0;
+ obj->ref--;
+ return -1;
+ }
+ }
+
+ obj->readbuf=g_malloc0(SND_CARD(obj)->bsize);
+ obj->writebuf=g_malloc0(SND_CARD(obj)->bsize);
+
+ SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED;
+ return 0;
+}
+
+void oss_card_close(OssCard *obj)
+{
+ int i;
+ obj->ref--;
+ if (obj->ref==0) {
+ close(obj->fd);
+ obj->fd=0;
+ SND_CARD(obj)->flags&=~SND_CARD_FLAGS_OPENED;
+ g_free(obj->readbuf);
+ obj->readbuf=NULL;
+ g_free(obj->writebuf);
+ obj->writebuf=NULL;
+
+ }
+}
+
+void oss_card_destroy(OssCard *obj)
+{
+ snd_card_uninit(SND_CARD(obj));
+ g_free(obj->dev_name);
+ g_free(obj->mixdev_name);
+ if (obj->readbuf!=NULL) g_free(obj->readbuf);
+ if (obj->writebuf!=NULL) g_free(obj->writebuf);
+}
+
+gboolean oss_card_can_read(OssCard *obj)
+{
+ struct timeval tout={0,0};
+ int err;
+ fd_set fdset;
+ if (obj->readpos!=0) return TRUE;
+ 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 oss_card_read(OssCard *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->readpos==0){
+ err=read(obj->fd,obj->readbuf,bsize);
+ if (err<0) {
+ g_warning("oss_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("oss_card_read: read-2() failed:%s.",strerror(errno));
+ }
+ return err;
+ }
+
+}
+
+int oss_card_write(OssCard *obj,char *buf,int size)
+{
+ int err;
+ gint bsize=SND_CARD(obj)->bsize;
+
+ if (size<bsize){
+ gint canwrite;
+ canwrite=MIN(bsize-obj->writepos,size);
+ memcpy(&obj->writebuf[obj->writepos],buf,canwrite);
+ obj->writepos+=canwrite;
+ if (obj->writepos>=bsize){
+ err=write(obj->fd,obj->writebuf,bsize);
+ obj->writepos=0;
+ }
+ return canwrite;
+ }else{
+ return write(obj->fd,buf,bsize);
+ }
+}
+
+void oss_card_set_level(OssCard *obj,gint way,gint a)
+{
+ int p,mix_fd;
+ int osscmd;
+ g_return_if_fail(obj->mixdev_name!=NULL);
+#ifdef HAVE_SYS_SOUNDCARD_H
+ switch(way){
+ case SND_CARD_LEVEL_GENERAL:
+ osscmd=SOUND_MIXER_VOLUME;
+ break;
+ case SND_CARD_LEVEL_INPUT:
+ osscmd=SOUND_MIXER_IGAIN;
+ break;
+ case SND_CARD_LEVEL_OUTPUT:
+ osscmd=SOUND_MIXER_PCM;
+ break;
+ default:
+ g_warning("oss_card_set_level: unsupported command.");
+ return;
+ }
+ p=(((int)a)<<8 | (int)a);
+ mix_fd = open(obj->mixdev_name, O_WRONLY);
+ ioctl(mix_fd,MIXER_WRITE(osscmd), &p);
+ close(mix_fd);
+#endif
+}
+
+gint oss_card_get_level(OssCard *obj,gint way)
+{
+ int p=0,mix_fd;
+ int osscmd;
+ g_return_if_fail(obj->mixdev_name!=NULL);
+#ifdef HAVE_SYS_SOUNDCARD_H
+ switch(way){
+ case SND_CARD_LEVEL_GENERAL:
+ osscmd=SOUND_MIXER_VOLUME;
+ break;
+ case SND_CARD_LEVEL_INPUT:
+ osscmd=SOUND_MIXER_IGAIN;
+ break;
+ case SND_CARD_LEVEL_OUTPUT:
+ osscmd=SOUND_MIXER_PCM;
+ break;
+ default:
+ g_warning("oss_card_get_level: unsupported command.");
+ return -1;
+ }
+ mix_fd = open(obj->mixdev_name, O_RDONLY);
+ ioctl(mix_fd,MIXER_READ(SOUND_MIXER_VOLUME), &p);
+ close(mix_fd);
+#endif
+ return p>>8;
+}
+
+void oss_card_set_source(OssCard *obj,int source)
+{
+ gint p=0;
+ gint mix_fd;
+ g_return_if_fail(obj->mixdev_name!=NULL);
+#ifdef HAVE_SYS_SOUNDCARD_H
+ if (source == 'c')
+ p = 1 << SOUND_MIXER_CD;
+ if (source == 'l')
+ p = 1 << SOUND_MIXER_LINE;
+ if (source == 'm')
+ p = 1 << SOUND_MIXER_MIC;
+
+
+ mix_fd = open(obj->mixdev_name, O_WRONLY);
+ ioctl(mix_fd, SOUND_MIXER_WRITE_RECSRC, &p);
+ close(mix_fd);
+#endif
+}
+
+MSFilter *oss_card_create_read_filter(OssCard *card)
+{
+ MSFilter *f=ms_oss_read_new();
+ ms_oss_read_set_device(MS_OSS_READ(f),SND_CARD(card)->index);
+ return f;
+}
+
+MSFilter *oss_card_create_write_filter(OssCard *card)
+{
+ MSFilter *f=ms_oss_write_new();
+ ms_oss_write_set_device(MS_OSS_WRITE(f),SND_CARD(card)->index);
+ return f;
+}
+
+
+SndCard * oss_card_new(char *devname, char *mixdev_name)
+{
+ OssCard * obj= g_new0(OssCard,1);
+ SndCard *base= SND_CARD(obj);
+ snd_card_init(base);
+ obj->dev_name=g_strdup(devname);
+ obj->mixdev_name=g_strdup( mixdev_name);
+#ifdef HAVE_GLIB
+ base->card_name=g_strdup_printf("%s (Open Sound System)",devname);
+#else
+ base->card_name=malloc(100);
+ snprintf(base->card_name, 100, "%s (Open Sound System)",devname);
+#endif
+ base->_probe=(SndCardOpenFunc)oss_card_probe;
+ base->_open_r=(SndCardOpenFunc)oss_card_open;
+ base->_open_w=(SndCardOpenFunc)oss_card_open;
+ base->_can_read=(SndCardPollFunc)oss_card_can_read;
+ base->_read=(SndCardIOFunc)oss_card_read;
+ base->_write=(SndCardIOFunc)oss_card_write;
+ base->_close_r=(SndCardCloseFunc)oss_card_close;
+ base->_close_w=(SndCardCloseFunc)oss_card_close;
+ base->_set_rec_source=(SndCardMixerSetRecSourceFunc)oss_card_set_source;
+ base->_set_level=(SndCardMixerSetLevelFunc)oss_card_set_level;
+ base->_get_level=(SndCardMixerGetLevelFunc)oss_card_get_level;
+ base->_destroy=(SndCardDestroyFunc)oss_card_destroy;
+ base->_create_read_filter=(SndCardCreateFilterFunc)oss_card_create_read_filter;
+ base->_create_write_filter=(SndCardCreateFilterFunc)oss_card_create_write_filter;
+ return base;
+}
+
+#define DSP_NAME "/dev/dsp"
+#define MIXER_NAME "/dev/mixer"
+
+gint oss_card_manager_init(SndCardManager *manager, gint tabindex)
+{
+ gchar *devname;
+ gchar *mixername;
+ gint devindex=0;
+ gint found=0;
+
+ /* search for /dev/dsp and /dev/mixer */
+#ifdef HAVE_GLIB
+ if (g_file_test(DSP_NAME,G_FILE_TEST_EXISTS)){
+ tabindex++;
+ devindex++;
+ manager->cards[0]=oss_card_new(DSP_NAME,MIXER_NAME);
+ manager->cards[0]->index=0;
+ found++;
+ g_message("Found /dev/dsp.");
+ }
+ for (;tabindex<MAX_SND_CARDS && devindex<MAX_SND_CARDS ;devindex++){
+ devname=g_strdup_printf("%s%i",DSP_NAME,devindex);
+ mixername=g_strdup_printf("%s%i",MIXER_NAME,devindex);
+ if (g_file_test(devname,G_FILE_TEST_EXISTS)){
+ manager->cards[tabindex]=oss_card_new(devname,mixername);
+ manager->cards[tabindex]->index=tabindex;
+ tabindex++;
+ found++;
+ }
+ g_free(devname);
+ g_free(mixername);
+ }
+#else
+ if (access(DSP_NAME,F_OK)==0){
+ tabindex++;
+ devindex++;
+ manager->cards[0]=oss_card_new(DSP_NAME,MIXER_NAME);
+ manager->cards[0]->index=0;
+ found++;
+ g_message("Found /dev/dsp.");
+ }
+ for (;tabindex<MAX_SND_CARDS && devindex<MAX_SND_CARDS ;devindex++){
+ devname=malloc(100);
+ snprintf(devname, 100, "%s%i",DSP_NAME,devindex);
+ mixername=malloc(100);
+ snprintf(mixername, 100, "%s%i",MIXER_NAME,devindex);
+
+ if (access(devname,F_OK)==0){
+ manager->cards[tabindex]=oss_card_new(devname,mixername);
+ manager->cards[tabindex]->index=tabindex;
+ tabindex++;
+ found++;
+ }
+ g_free(devname);
+ g_free(mixername);
+ }
+#endif
+ if (tabindex==0) g_warning("No sound cards found !");
+ return found;
+}
+
+
+#endif