summaryrefslogtreecommitdiffstats
path: root/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/alsacard.c
diff options
context:
space:
mode:
Diffstat (limited to 'kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/alsacard.c')
-rw-r--r--kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/alsacard.c640
1 files changed, 640 insertions, 0 deletions
diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/alsacard.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/alsacard.c
new file mode 100644
index 00000000..c240aa72
--- /dev/null
+++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/alsacard.c
@@ -0,0 +1,640 @@
+/*
+ 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 "alsacard.h"
+
+#ifdef HAVE_ALSA_ASOUNDLIB_H
+
+static gchar *over_pcmdev=NULL;
+
+#include "msossread.h"
+#include "msosswrite.h"
+
+#include <signal.h>
+
+int __alsa_card_write(AlsaCard *obj,char *buf,int size);
+
+int alsa_set_params(AlsaCard *obj, int rw, int bits, int stereo, int rate)
+{
+ snd_pcm_hw_params_t *hwparams=NULL;
+ snd_pcm_sw_params_t *swparams=NULL;
+ snd_pcm_t *pcm_handle;
+ gint dir,exact_value;
+ gint channels;
+ gint fsize=0;
+ gint periods=8;
+ gint periodsize=256;
+ gint err;
+ int format;
+
+ if (rw) {
+ pcm_handle=obj->write_handle;
+ }
+ else pcm_handle=obj->read_handle;
+
+ /* Allocate the snd_pcm_hw_params_t structure on the stack. */
+ snd_pcm_hw_params_alloca(&hwparams);
+
+ /* Init hwparams with full configuration space */
+ if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) {
+ g_warning("alsa_set_params: Cannot configure this PCM device.\n");
+ return(-1);
+ }
+
+ if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
+ g_warning("alsa_set_params: Error setting access.\n");
+ return(-1);
+ }
+ /* Set sample format */
+#ifdef WORDS_BIGENDIAN
+ format=SND_PCM_FORMAT_S16_BE;
+#else
+ format=SND_PCM_FORMAT_S16_LE;
+#endif
+ if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, format) < 0) {
+ g_warning("alsa_set_params: Error setting format.\n");
+ return(-1);
+ }
+ /* Set number of channels */
+ if (stereo) channels=2;
+ else channels=1;
+ if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, channels) < 0) {
+ g_warning("alsa_set_params: Error setting channels.\n");
+ return(-1);
+ }
+ /* Set sample rate. If the exact rate is not supported */
+ /* by the hardware, use nearest possible rate. */
+ exact_value=rate;
+ dir=0;
+ if ((err=snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_value, &dir))<0){
+ g_warning("alsa_set_params: Error setting rate to %i:%s",rate,snd_strerror(err));
+ return -1;
+ }
+ if (dir != 0) {
+ g_warning("alsa_set_params: The rate %d Hz is not supported by your hardware.\n "
+ "==> Using %d Hz instead.\n", rate, exact_value);
+ }
+ /* choose greater period size when rate is high */
+ periodsize=periodsize*(rate/8000);
+
+ /* Set buffer size (in frames). The resulting latency is given by */
+ /* latency = periodsize * periods / (rate * bytes_per_frame) */
+ /*
+ fsize=periodsize * periods;
+ exact_value=fsize;
+ if ((err=snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams,&exact_value)) < 0) {
+ g_warning("alsa_set_params: Error setting buffer size:%s",snd_strerror(err));
+ return(-1);
+ }
+ if (fsize!= exact_value) {
+ g_warning("alsa_set_params: The buffer size %d is not supported by your hardware.\n "
+ "==> Using %d instead.\n", fsize, exact_value);
+ }
+ */
+ /* set period size */
+ exact_value=periodsize;
+ dir=0;
+ if (snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &exact_value, &dir) < 0) {
+ g_warning("alsa_set_params: Error setting period size.\n");
+ return(-1);
+ }
+ if (dir != 0) {
+ g_warning("alsa_set_params: The period size %d is not supported by your hardware.\n "
+ "==> Using %d instead.\n", periodsize, exact_value);
+ }
+ periodsize=exact_value;
+ /* Set number of periods. Periods used to be called fragments. */
+ exact_value=periods;
+ dir=0;
+ if (snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &exact_value, &dir) < 0) {
+ g_warning("alsa_set_params: Error setting periods.\n");
+ return(-1);
+ }
+ if (dir != 0) {
+ g_warning("alsa_set_params: The number of periods %d is not supported by your hardware.\n "
+ "==> Using %d instead.\n", periods, exact_value);
+ }
+ /* Apply HW parameter settings to */
+ /* PCM device and prepare device */
+ if ((err=snd_pcm_hw_params(pcm_handle, hwparams)) < 0) {
+ g_warning("alsa_set_params: Error setting HW params:%s",snd_strerror(err));
+ return(-1);
+ }
+ /*prepare sw params */
+ if (rw){
+ snd_pcm_sw_params_alloca(&swparams);
+ snd_pcm_sw_params_current(pcm_handle, swparams);
+ if ((err=snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams,periodsize*2 ))<0){
+ g_warning("alsa_set_params: Error setting start threshold:%s",snd_strerror(err));
+ return -1;
+ }
+ if ((err=snd_pcm_sw_params(pcm_handle, swparams))<0){
+ g_warning("alsa_set_params: Error setting SW params:%s",snd_strerror(err));
+ return(-1);
+ }
+ }
+ obj->frame_size=channels*(bits/8);
+ SND_CARD(obj)->bsize=periodsize*obj->frame_size;
+ /* //SND_CARD(obj)->bsize=4096; */
+ obj->frames=periodsize;
+ g_message("alsa_set_params: blocksize=%i.",SND_CARD(obj)->bsize);
+ return SND_CARD(obj)->bsize;
+}
+
+int alsa_card_open_r(AlsaCard *obj,int bits,int stereo,int rate)
+{
+ int bsize;
+ int err;
+ snd_pcm_t *pcm_handle;
+ gchar *pcmdev;
+ if (over_pcmdev!=NULL) pcmdev=over_pcmdev;
+ else pcmdev=obj->pcmdev;
+
+ if (snd_pcm_open(&pcm_handle, pcmdev,SND_PCM_STREAM_CAPTURE,SND_PCM_NONBLOCK) < 0) {
+ g_warning("alsa_card_open_r: Error opening PCM device %s\n",obj->pcmdev );
+ return -1;
+ }
+ g_return_val_if_fail(pcm_handle!=NULL,-1);
+ obj->read_handle=pcm_handle;
+ if ((bsize=alsa_set_params(obj,0,bits,stereo,rate))<0){
+ snd_pcm_close(pcm_handle);
+ obj->read_handle=NULL;
+ return -1;
+ }
+ obj->readbuf=g_malloc0(bsize);
+
+ err=snd_pcm_start(obj->read_handle);
+ if (err<0){
+ g_warning("Cannot start read pcm: %s", snd_strerror(err));
+ }
+ obj->readpos=0;
+ SND_CARD(obj)->bsize=bsize;
+ SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED;
+ return 0;
+}
+
+int alsa_card_open_w(AlsaCard *obj,int bits,int stereo,int rate)
+{
+ int err,bsize;
+ snd_pcm_t *pcm_handle;
+ gchar *pcmdev;
+ if (over_pcmdev!=NULL) pcmdev=over_pcmdev;
+ else pcmdev=obj->pcmdev;
+
+ if (snd_pcm_open(&pcm_handle, pcmdev,SND_PCM_STREAM_PLAYBACK,SND_PCM_NONBLOCK) < 0) {
+ g_warning("alsa_card_open_w: Error opening PCM device %s\n", obj->pcmdev);
+ return -1;
+ }
+ obj->write_handle=pcm_handle;
+ if ((bsize=alsa_set_params(obj,1,bits,stereo,rate))<0){
+ snd_pcm_close(pcm_handle);
+ obj->write_handle=NULL;
+ return -1;
+ }
+ obj->writebuf=g_malloc0(bsize);
+
+ obj->writepos=0;
+ SND_CARD(obj)->bsize=bsize;
+ SND_CARD(obj)->flags|=SND_CARD_FLAGS_OPENED;
+ return 0;
+}
+
+
+void alsa_card_set_blocking_mode(AlsaCard *obj, gboolean yesno){
+ if (obj->read_handle!=NULL) snd_pcm_nonblock(obj->read_handle,!yesno);
+ if (obj->write_handle!=NULL) snd_pcm_nonblock(obj->write_handle,!yesno);
+}
+
+void alsa_card_close_r(AlsaCard *obj)
+{
+ if (obj->read_handle!=NULL){
+ snd_pcm_close(obj->read_handle);
+ obj->read_handle=NULL;
+ g_free(obj->readbuf);
+ obj->readbuf=NULL;
+ }
+}
+
+void alsa_card_close_w(AlsaCard *obj)
+{
+ if (obj->write_handle!=NULL){
+ snd_pcm_close(obj->write_handle);
+ obj->write_handle=NULL;
+ g_free(obj->writebuf);
+ obj->writebuf=NULL;
+ }
+}
+
+int alsa_card_probe(AlsaCard *obj,int bits,int stereo,int rate)
+{
+ int ret;
+ ret=alsa_card_open_w(obj,bits,stereo,rate);
+ if (ret<0) return -1;
+ ret=SND_CARD(obj)->bsize;
+ alsa_card_close_w(obj);
+ return ret;
+}
+
+
+void alsa_card_destroy(AlsaCard *obj)
+{
+ snd_card_uninit(SND_CARD(obj));
+ g_free(obj->pcmdev);
+ if (obj->readbuf!=0) g_free(obj->readbuf);
+ if (obj->writebuf!=0) g_free(obj->writebuf);
+}
+
+gboolean alsa_card_can_read(AlsaCard *obj)
+{
+ int frames;
+ g_return_val_if_fail(obj->read_handle!=NULL,0);
+ if (obj->readpos!=0) return TRUE;
+ if ( frames=snd_pcm_avail_update(obj->read_handle)>=obj->frames) return 1;
+ /* //g_message("frames=%i",frames); */
+ return 0;
+}
+
+
+
+int __alsa_card_read(AlsaCard *obj,char *buf,int bsize)
+{
+ int err;
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set,SIGALRM);
+ sigprocmask(SIG_BLOCK,&set,NULL);
+ err=snd_pcm_readi(obj->read_handle,buf,bsize/obj->frame_size);
+ if (err<0) {
+ if (err!=-EPIPE){
+ g_warning("alsa_card_read: snd_pcm_readi() failed:%s.",snd_strerror(err));
+ }
+ snd_pcm_prepare(obj->read_handle);
+ err=snd_pcm_readi(obj->read_handle,buf,bsize/obj->frame_size);
+ if (err<0) g_warning("alsa_card_read: snd_pcm_readi() failed:%s.",snd_strerror(err));
+ }
+ sigprocmask(SIG_UNBLOCK,&set,NULL);
+ return err*obj->frame_size;
+}
+
+int alsa_card_read(AlsaCard *obj,char *buf,int size)
+{
+ int err;
+ gint bsize=SND_CARD(obj)->bsize;
+ g_return_val_if_fail(obj->read_handle!=NULL,-1);
+ if (size<bsize){
+ gint canread=MIN(bsize-obj->readpos,size);
+
+ if (obj->readpos==0){
+ err=__alsa_card_read(obj,obj->readbuf,bsize);
+ }
+
+ memcpy(buf,&obj->readbuf[obj->readpos],canread);
+ obj->readpos+=canread;
+ if (obj->readpos>=bsize) obj->readpos=0;
+ return canread;
+ }else{
+ err=__alsa_card_read(obj,buf,size);
+ return err;
+ }
+
+}
+
+int __alsa_card_write(AlsaCard *obj,char *buf,int size)
+{
+ int err;
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set,SIGALRM);
+ sigprocmask(SIG_BLOCK,&set,NULL);
+ if ((err=snd_pcm_writei(obj->write_handle,buf,size/obj->frame_size))<0){
+ if (err!=-EPIPE){
+ g_warning("alsa_card_write: snd_pcm_writei() failed:%s.",snd_strerror(err));
+ }
+ snd_pcm_prepare(obj->write_handle);
+ err=snd_pcm_writei(obj->write_handle,buf,size/obj->frame_size);
+ if (err<0) g_warning("alsa_card_write: Error writing sound buffer (size=%i):%s",size,snd_strerror(err));
+
+ }
+ sigprocmask(SIG_UNBLOCK,&set,NULL);
+ return err;
+}
+
+int alsa_card_write(AlsaCard *obj,char *buf,int size)
+{
+ int err;
+ gint bsize=SND_CARD(obj)->bsize;
+ g_return_val_if_fail(obj->write_handle!=NULL,-1);
+ 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=__alsa_card_write(obj,obj->writebuf,bsize);
+ obj->writepos=0;
+ }
+ return canwrite;
+ }else{
+ return __alsa_card_write(obj,buf,bsize);
+ }
+}
+
+snd_mixer_t *alsa_mixer_open(AlsaCard *obj){
+ snd_mixer_t *mixer=NULL;
+ int err;
+ err=snd_mixer_open(&mixer,0);
+ if (err<0){
+ g_warning("Could not open alsa mixer: %s",snd_strerror(err));
+ return NULL;
+ }
+ if ((err = snd_mixer_attach (mixer, obj->mixdev)) < 0){
+ g_warning("Could not attach mixer to card: %s",snd_strerror(err));
+ snd_mixer_close(mixer);
+ return NULL;
+ }
+ if ((err = snd_mixer_selem_register (mixer, NULL, NULL)) < 0){
+ g_warning("snd_mixer_selem_register: %s",snd_strerror(err));
+ snd_mixer_close(mixer);
+ return NULL;
+ }
+ if ((err = snd_mixer_load (mixer)) < 0){
+ g_warning("snd_mixer_load: %s",snd_strerror(err));
+ snd_mixer_close(mixer);
+ return NULL;
+ }
+ obj->mixer=mixer;
+ return mixer;
+}
+
+void alsa_mixer_close(AlsaCard *obj){
+ snd_mixer_close(obj->mixer);
+ obj->mixer=NULL;
+}
+
+typedef enum {CAPTURE, PLAYBACK, CAPTURE_SWITCH, PLAYBACK_SWITCH} MixerAction;
+
+static gint get_mixer_element(snd_mixer_t *mixer,const char *name, MixerAction action){
+ long value=0;
+ const char *elemname;
+ snd_mixer_elem_t *elem;
+ int err;
+ long sndMixerPMin;
+ long sndMixerPMax;
+ long newvol;
+ elem=snd_mixer_first_elem(mixer);
+ while (elem!=NULL){
+ elemname=snd_mixer_selem_get_name(elem);
+ /* //g_message("Found alsa mixer element %s.",elemname); */
+ if (strcmp(elemname,name)==0){
+ switch (action){
+ case CAPTURE:
+ if (snd_mixer_selem_has_capture_volume(elem)){
+ snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax);
+ err=snd_mixer_selem_get_capture_volume(elem,SND_MIXER_SCHN_UNKNOWN,&newvol);
+ newvol-=sndMixerPMin;
+ value=(100*newvol)/(sndMixerPMax-sndMixerPMin);
+ if (err<0) g_warning("Could not get capture volume for %s:%s",name,snd_strerror(err));
+ /* //else g_message("Succesfully get capture level for %s.",elemname); */
+ break;
+ }
+ break;
+ case PLAYBACK:
+ if (snd_mixer_selem_has_playback_volume(elem)){
+ snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax);
+ err=snd_mixer_selem_get_playback_volume(elem,SND_MIXER_SCHN_FRONT_LEFT,&newvol);
+ newvol-=sndMixerPMin;
+ value=(100*newvol)/(sndMixerPMax-sndMixerPMin);
+ if (err<0) g_warning("Could not get playback volume for %s:%s",name,snd_strerror(err));
+ /* //else g_message("Succesfully get playback level for %s.",elemname); */
+ break;
+ }
+ break;
+ case CAPTURE_SWITCH:
+
+ break;
+ }
+ }
+ elem=snd_mixer_elem_next(elem);
+ }
+
+ return value;
+}
+
+
+static void set_mixer_element(snd_mixer_t *mixer,const char *name, gint level,MixerAction action){
+ const char *elemname;
+ snd_mixer_elem_t *elem;
+ int tmp;
+ long sndMixerPMin;
+ long sndMixerPMax;
+ long newvol;
+
+ elem=snd_mixer_first_elem(mixer);
+
+ while (elem!=NULL){
+ elemname=snd_mixer_selem_get_name(elem);
+ /* //g_message("Found alsa mixer element %s.",elemname); */
+ if (strcmp(elemname,name)==0){
+ switch(action){
+ case CAPTURE:
+ if (snd_mixer_selem_has_capture_volume(elem)){
+ snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax);
+ newvol=(((sndMixerPMax-sndMixerPMin)*level)/100)+sndMixerPMin;
+ snd_mixer_selem_set_capture_volume_all(elem,newvol);
+ /* //g_message("Succesfully set capture level for %s.",elemname); */
+ return;
+ }
+ break;
+ case PLAYBACK:
+ if (snd_mixer_selem_has_playback_volume(elem)){
+ snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax);
+ newvol=(((sndMixerPMax-sndMixerPMin)*level)/100)+sndMixerPMin;
+ snd_mixer_selem_set_playback_volume_all(elem,newvol);
+ /* //g_message("Succesfully set playback level for %s.",elemname); */
+ return;
+ }
+ break;
+ case CAPTURE_SWITCH:
+ if (snd_mixer_selem_has_capture_switch(elem)){
+ snd_mixer_selem_set_capture_switch_all(elem,level);
+ /* //g_message("Succesfully set capture switch for %s.",elemname); */
+ }
+ break;
+ case PLAYBACK_SWITCH:
+ if (snd_mixer_selem_has_playback_switch(elem)){
+ snd_mixer_selem_set_playback_switch_all(elem,level);
+ /* //g_message("Succesfully set capture switch for %s.",elemname); */
+ }
+ break;
+
+ }
+ }
+ elem=snd_mixer_elem_next(elem);
+ }
+
+ return ;
+}
+
+
+void alsa_card_set_level(AlsaCard *obj,gint way,gint a)
+{
+ snd_mixer_t *mixer;
+ mixer=alsa_mixer_open(obj);
+ if (mixer==NULL) return ;
+ switch(way){
+ case SND_CARD_LEVEL_GENERAL:
+ set_mixer_element(mixer,"Master",a,PLAYBACK);
+ break;
+ case SND_CARD_LEVEL_INPUT:
+ set_mixer_element(mixer,"Capture",a,CAPTURE);
+ break;
+ case SND_CARD_LEVEL_OUTPUT:
+ set_mixer_element(mixer,"PCM",a,PLAYBACK);
+ break;
+ default:
+ g_warning("oss_card_set_level: unsupported command.");
+ }
+ alsa_mixer_close(obj);
+}
+
+gint alsa_card_get_level(AlsaCard *obj,gint way)
+{
+ snd_mixer_t *mixer;
+ gint value;
+ mixer=alsa_mixer_open(obj);
+ if (mixer==NULL) return 0;
+ switch(way){
+ case SND_CARD_LEVEL_GENERAL:
+ value=get_mixer_element(mixer,"Master",PLAYBACK);
+ break;
+ case SND_CARD_LEVEL_INPUT:
+ value=get_mixer_element(mixer,"Capture",CAPTURE);
+ break;
+ case SND_CARD_LEVEL_OUTPUT:
+ value=get_mixer_element(mixer,"PCM",PLAYBACK);
+ break;
+ default:
+ g_warning("oss_card_set_level: unsupported command.");
+ }
+ alsa_mixer_close(obj);
+ return value;
+}
+
+void alsa_card_set_source(AlsaCard *obj,int source)
+{
+ snd_mixer_t *mixer;
+ mixer=alsa_mixer_open(obj);
+ if (mixer==NULL) return;
+ switch (source){
+ case 'm':
+ set_mixer_element(mixer,"Mic",1,CAPTURE_SWITCH);
+ set_mixer_element(mixer,"Capture",1,CAPTURE_SWITCH);
+ break;
+ case 'l':
+ set_mixer_element(mixer,"Line",1,CAPTURE_SWITCH);
+ set_mixer_element(mixer,"Capture",1,CAPTURE_SWITCH);
+ break;
+ }
+}
+
+MSFilter *alsa_card_create_read_filter(AlsaCard *card)
+{
+ MSFilter *f=ms_oss_read_new();
+ ms_oss_read_set_device(MS_OSS_READ(f),SND_CARD(card)->index);
+ return f;
+}
+
+MSFilter *alsa_card_create_write_filter(AlsaCard *card)
+{
+ MSFilter *f=ms_oss_write_new();
+ ms_oss_write_set_device(MS_OSS_WRITE(f),SND_CARD(card)->index);
+ return f;
+}
+
+
+SndCard * alsa_card_new(gint devid)
+{
+ AlsaCard * obj;
+ SndCard *base;
+ int err;
+ gchar *name=NULL;
+
+ /* carefull: this is an alsalib call despite its name! */
+ err=snd_card_get_name(devid,&name);
+ if (err<0) {
+ return NULL;
+ }
+ obj= g_new0(AlsaCard,1);
+ base= SND_CARD(obj);
+ snd_card_init(base);
+
+ base->card_name=g_strdup_printf("%s (Advanced Linux Sound Architecture)",name);
+ base->_probe=(SndCardOpenFunc)alsa_card_probe;
+ base->_open_r=(SndCardOpenFunc)alsa_card_open_r;
+ base->_open_w=(SndCardOpenFunc)alsa_card_open_w;
+ base->_can_read=(SndCardPollFunc)alsa_card_can_read;
+ base->_set_blocking_mode=(SndCardSetBlockingModeFunc)alsa_card_set_blocking_mode;
+ base->_read=(SndCardIOFunc)alsa_card_read;
+ base->_write=(SndCardIOFunc)alsa_card_write;
+ base->_close_r=(SndCardCloseFunc)alsa_card_close_r;
+ base->_close_w=(SndCardCloseFunc)alsa_card_close_w;
+ base->_set_rec_source=(SndCardMixerSetRecSourceFunc)alsa_card_set_source;
+ base->_set_level=(SndCardMixerSetLevelFunc)alsa_card_set_level;
+ base->_get_level=(SndCardMixerGetLevelFunc)alsa_card_get_level;
+ base->_destroy=(SndCardDestroyFunc)alsa_card_destroy;
+ base->_create_read_filter=(SndCardCreateFilterFunc)alsa_card_create_read_filter;
+ base->_create_write_filter=(SndCardCreateFilterFunc)alsa_card_create_write_filter;
+
+
+ obj->pcmdev=g_strdup_printf("plughw:%i,0",devid);
+ obj->mixdev=g_strdup_printf("hw:%i",devid);
+ obj->readbuf=NULL;
+ obj->writebuf=NULL;
+ return base;
+}
+
+
+gint alsa_card_manager_init(SndCardManager *m, gint index)
+{
+ gint devindex;
+ gint i;
+ gint found=0;
+ gchar *name=NULL;
+ for(devindex=0;index<MAX_SND_CARDS && devindex<MAX_SND_CARDS ;devindex++){
+ if (snd_card_get_name(devindex,&name)==0){
+ g_message("Found ALSA device: %s",name);
+ m->cards[index]=alsa_card_new(devindex);
+ m->cards[index]->index=index;
+ found++;
+ index++;
+ }
+ }
+ return found;
+}
+
+void alsa_card_manager_set_default_pcm_device(const gchar *pcmdev){
+ if (over_pcmdev!=NULL){
+ g_free(over_pcmdev);
+ }
+ over_pcmdev=g_strdup(pcmdev);
+}
+
+#endif