⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alsa.c

📁 基于osip、eXosip、speex、ffmpeg的VoIP源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		case MS_SND_CARD_CAPTURE:			value=get_mixer_element(mixer,"Capture",CAPTURE);			break;		case MS_SND_CARD_PLAYBACK:			value=get_mixer_element(mixer,"PCM",PLAYBACK);			break;		default:			ms_warning("alsa_card_set_level: unsupported command.");	}	alsa_mixer_close(mixer);	return value;}static void alsa_card_set_source(MSSndCard *obj,MSSndCardCapture source){	snd_mixer_t *mixer;	AlsaData *ad=(AlsaData*)obj->data;	mixer=alsa_mixer_open(ad->mixdev);	if (mixer==NULL) return;	switch (source){		case MS_SND_CARD_MIC:			set_mixer_element(mixer,"Mic",1,CAPTURE_SWITCH);			set_mixer_element(mixer,"Capture",1,CAPTURE_SWITCH);			break;		case MS_SND_CARD_LINE:			set_mixer_element(mixer,"Line",1,CAPTURE_SWITCH);			set_mixer_element(mixer,"Capture",1,CAPTURE_SWITCH);			break;	}	alsa_mixer_close(mixer);}static MSFilter *alsa_card_create_reader(MSSndCard *card){	AlsaData *ad=(AlsaData*)card->data;	MSFilter *f=ms_alsa_read_new(ad->pcmdev);	return f;}static MSFilter *alsa_card_create_writer(MSSndCard *card){	AlsaData *ad=(AlsaData*)card->data;	MSFilter *f=ms_alsa_write_new(ad->pcmdev);	return f;}static void alsa_card_init(MSSndCard *obj){	AlsaData *ad=ms_new0(AlsaData,1);	obj->data=ad;}static void alsa_card_uninit(MSSndCard *obj){	AlsaData *ad=(AlsaData*)obj->data;	if (ad->pcmdev!=NULL) ms_free(ad->pcmdev);	if (ad->mixdev!=NULL) ms_free(ad->mixdev);	ms_free(ad);}static void alsa_card_detect(MSSndCardManager *m){	int i;	for (i=-1;i<10;i++){		MSSndCard *card=alsa_card_new(i);		if (card!=NULL)			ms_snd_card_manager_add_card(m,card);	}}MSSndCardDesc alsa_card_desc={	.driver_type="ALSA",	.detect=alsa_card_detect,	.init=alsa_card_init,	.set_level=alsa_card_set_level,	.get_level=alsa_card_get_level,	.set_capture=alsa_card_set_source,	.create_reader=alsa_card_create_reader,	.create_writer=alsa_card_create_writer,	.uninit=alsa_card_uninit,	.duplicate=alsa_card_duplicate};static MSSndCard *alsa_card_duplicate(MSSndCard *obj){	MSSndCard *card=ms_snd_card_new(&alsa_card_desc);	AlsaData* dcard=(AlsaData*)card->data;	AlsaData* dobj=(AlsaData*)obj->data;	card->name=ms_strdup(obj->name);	card->id=ms_strdup(obj->id);	dcard->pcmdev=ms_strdup(dobj->pcmdev);	dcard->mixdev=ms_strdup(dobj->mixdev);	return card;}MSSndCard * ms_alsa_card_new_custom(const char *pcmdev, const char *mixdev){	MSSndCard * obj;	AlsaData *ad;	obj=ms_snd_card_new(&alsa_card_desc);	ad=(AlsaData*)obj->data;	obj->name=ms_strdup(pcmdev);	ad->pcmdev=ms_strdup(pcmdev);	ad->mixdev=ms_strdup(mixdev);	return obj;}static MSSndCard * alsa_card_new(int id){	MSSndCard * obj;	char *name=NULL;	AlsaData *ad;	int err;	if (id!=-1){		err=snd_card_get_name(id,&name);		if (err<0) {			return NULL;		}	}	obj=ms_snd_card_new(&alsa_card_desc);	ad=(AlsaData*)obj->data;	if (id==-1) {		/* the default pcm device */		obj->name=ms_strdup("default device");		ad->pcmdev=ms_strdup("default");		ad->mixdev=ms_strdup("default");	}else{		/* remove trailing spaces from card name */		char *pos1, *pos2;		pos1=ms_strdup(name);		pos2=pos1+strlen(pos1)-1;		for (; pos2>pos1 && *pos2==' '; pos2--) *pos2='\0';		obj->name=pos1;		ad->pcmdev=ms_strdup_printf("default:%i",id);		ad->mixdev=ms_strdup_printf("default:%i",id);	}	free(name);	/*ms_message("alsa device %s found",obj->name);*/	return obj;}struct _AlsaReadData{	char *pcmdev;	snd_pcm_t *handle;	int rate;	int nchannels;#ifdef THREADED_VERSION	ms_thread_t thread;	ms_mutex_t mutex;	MSBufferizer * bufferizer;	bool_t read_started;	bool_t write_started;#endif};typedef struct _AlsaReadData AlsaReadData;void alsa_read_init(MSFilter *obj){	AlsaReadData *ad=ms_new(AlsaReadData,1);	ad->pcmdev=NULL;	ad->handle=NULL;	ad->rate=8000;	ad->nchannels=1;	obj->data=ad;#ifdef THREADED_VERSION	ad->read_started=FALSE;	ad->write_started=FALSE;	ad->bufferizer=ms_bufferizer_new();	ms_mutex_init(&ad->mutex,NULL);	ad->thread=0;#endif}#ifdef THREADED_VERSIONstatic void * alsa_write_thread(void *p){	AlsaReadData *ad=(AlsaReadData*)p;	int samples=(160*ad->rate)/8000;	int err;	int count=0;	mblk_t *om=NULL;	struct timeval timeout;	if (ad->handle==NULL && ad->pcmdev!=NULL){		ad->handle=alsa_open_r(ad->pcmdev,16,ad->nchannels==2,ad->rate);	}	if (ad->handle==NULL) return NULL;	while (ad->read_started)	  {	    count = alsa_can_read(ad->handle,samples);	    if (count==24)	      { /* keep this value for this driver */ }	    else if (count<=0)	      {		count = samples;	      }	    else if (count>0)	      {		//ms_warning("%i count", count);		//count = samples;	      }	    int size=count*2;	    om=allocb(size,0);	    if ((err=alsa_read(ad->handle,om->b_wptr,count))<=0)	      {		ms_warning("nothing to read");		//ms_warning("Fail to read samples %i", count);		continue;	      }	    //ms_warning(" read %i", err);	    	    size=err*2;	    om->b_wptr+=size;	    ms_mutex_lock(&ad->mutex);	    ms_bufferizer_put(ad->bufferizer,om);	    ms_mutex_unlock(&ad->mutex);	    if (count==24)	      {		timeout.tv_sec = 0;		timeout.tv_usec = 2000;		select(0, 0, NULL, NULL, &timeout );	      }	    else	      {		/* select will be less active than locking on "read" */		timeout.tv_sec = 0;		timeout.tv_usec = 5000;		select(0, 0, NULL, NULL, &timeout );	      }	  }	if (ad->handle!=NULL) snd_pcm_close(ad->handle);	ad->handle=NULL;	return NULL;}static void alsa_start_r(AlsaReadData *d){	if (d->read_started==FALSE){		d->read_started=TRUE;		ms_thread_create(&d->thread,NULL,alsa_write_thread,d);	}else d->read_started=TRUE;}static void alsa_stop_r(AlsaReadData *d){	d->read_started=FALSE;	if (d->thread!=0)	  {	    ms_thread_join(d->thread,NULL);	    d->thread=0;	  }}#endif#ifdef THREADED_VERSIONvoid alsa_read_preprocess(MSFilter *obj){	AlsaReadData *ad=(AlsaReadData*)obj->data;	alsa_start_r(ad);}#endifvoid alsa_read_postprocess(MSFilter *obj){	AlsaReadData *ad=(AlsaReadData*)obj->data;#ifdef THREADED_VERSION	alsa_stop_r(ad);#endif	if (ad->handle!=NULL) snd_pcm_close(ad->handle);	ad->handle=NULL;}void alsa_read_uninit(MSFilter *obj){	AlsaReadData *ad=(AlsaReadData*)obj->data;#ifdef THREADED_VERSION	alsa_stop_r(ad);#endif	if (ad->pcmdev!=NULL) ms_free(ad->pcmdev);	if (ad->handle!=NULL) snd_pcm_close(ad->handle);#ifdef THREADED_VERSION	ms_bufferizer_destroy(ad->bufferizer);	ms_mutex_destroy(&ad->mutex);#endif	ms_free(ad);}#ifndef THREADED_VERSIONvoid alsa_read_process(MSFilter *obj){	AlsaReadData *ad=(AlsaReadData*)obj->data;	int samples=(128*ad->rate)/8000;	int err;	mblk_t *om=NULL;	if (ad->handle==NULL && ad->pcmdev!=NULL){		ad->handle=alsa_open_r(ad->pcmdev,16,ad->nchannels==2,ad->rate);	}	if (ad->handle==NULL) return;	while (alsa_can_read(ad->handle,samples)>=samples){	  		int size=samples*2;		om=allocb(size,0);		if ((err=alsa_read(ad->handle,om->b_wptr,samples))<=0) {			ms_warning("Fail to read samples");			freemsg(om);			return;		}		size=err*2;		om->b_wptr+=size;		/*ms_message("alsa_read_process: Outputing %i bytes",size);*/		ms_queue_put(obj->outputs[0],om);	}}#endif#ifdef THREADED_VERSIONvoid alsa_read_process(MSFilter *obj){	AlsaReadData *ad=(AlsaReadData*)obj->data;	mblk_t *om=NULL;	int samples=(160*ad->rate)/8000;	ms_mutex_lock(&ad->mutex);	while (ms_bufferizer_get_avail(ad->bufferizer)>=samples*2){	  	  om=allocb(samples*2,0);	  ms_bufferizer_read(ad->bufferizer,om->b_wptr,samples*2);	  	  om->b_wptr+=samples*2;	  /*ms_message("alsa_read_process: Outputing %i bytes",size);*/	  ms_queue_put(obj->outputs[0],om);	}	ms_mutex_unlock(&ad->mutex);}#endifstatic int alsa_read_set_sample_rate(MSFilter *obj, void *param){	AlsaReadData *ad=(AlsaReadData*)obj->data;	ad->rate=*((int*)param);	return 0;}static int alsa_read_set_nchannels(MSFilter *obj, void *param){	AlsaReadData *ad=(AlsaReadData*)obj->data;	ad->nchannels=*((int*)param);	return 0;}MSFilterMethod alsa_read_methods[]={	{MS_FILTER_SET_SAMPLE_RATE, alsa_read_set_sample_rate},	{MS_FILTER_SET_SAMPLE_RATE, alsa_read_set_nchannels},	{0,NULL}};MSFilterDesc alsa_read_desc={	.id=MS_ALSA_READ_ID,	.name="MSAlsaRead",	.text="Alsa sound source",	.category=MS_FILTER_OTHER,	.ninputs=0,	.noutputs=1,	.init=alsa_read_init,#ifdef THREADED_VERSION	.preprocess=alsa_read_preprocess,#endif	.process=alsa_read_process,	.postprocess=alsa_read_postprocess,	.uninit=alsa_read_uninit,	.methods=alsa_read_methods};static MSFilter * ms_alsa_read_new(const char *dev){	MSFilter *f=ms_filter_new_from_desc(&alsa_read_desc);	AlsaReadData *ad=(AlsaReadData*)f->data;	ad->pcmdev=ms_strdup(dev);	return f;}typedef struct _AlsaReadData AlsaWriteData;void alsa_write_init(MSFilter *obj){	AlsaWriteData *ad=ms_new(AlsaWriteData,1);	ad->pcmdev=NULL;	ad->handle=NULL;	ad->rate=8000;	ad->nchannels=1;	obj->data=ad;}void alsa_write_postprocess(MSFilter *obj){	AlsaReadData *ad=(AlsaReadData*)obj->data;	if (ad->handle!=NULL) snd_pcm_close(ad->handle);	ad->handle=NULL;}void alsa_write_uninit(MSFilter *obj){	AlsaWriteData *ad=(AlsaWriteData*)obj->data;	if (ad->pcmdev!=NULL) ms_free(ad->pcmdev);	if (ad->handle!=NULL) snd_pcm_close(ad->handle);	ms_free(ad);}int alsa_write_set_sample_rate(MSFilter *obj, void *data){	int *rate=(int*)data;	AlsaWriteData *ad=(AlsaWriteData*)obj->data;	ad->rate=*rate;	return 0;}int alsa_write_set_nchannels(MSFilter *obj, void *data){	int *n=(int*)data;	AlsaWriteData *ad=(AlsaWriteData*)obj->data;	ad->nchannels=*n;	return 0;}void alsa_write_process(MSFilter *obj){	AlsaWriteData *ad=(AlsaWriteData*)obj->data;	mblk_t *im=NULL;	int size;	int samples;	int err;	if (ad->handle==NULL && ad->pcmdev!=NULL){		ad->handle=alsa_open_w(ad->pcmdev,16,ad->nchannels==2,ad->rate);#ifdef EPIPE_BUGFIX		alsa_fill_w (ad->pcmdev);#endif	}	if (ad->handle==NULL) {		ms_queue_flush(obj->inputs[0]);		return;	}	while ((im=ms_queue_get(obj->inputs[0]))!=NULL){		while((size=im->b_wptr-im->b_rptr)>0){			samples=size/(2*ad->nchannels);			err=alsa_write(ad->handle,im->b_rptr,samples);			if (err>0) {				im->b_rptr+=err*(2*ad->nchannels);			}			else break;		}		freemsg(im);	}}MSFilterMethod alsa_write_methods[]={	{MS_FILTER_SET_SAMPLE_RATE, alsa_write_set_sample_rate},	{MS_FILTER_SET_NCHANNELS, alsa_write_set_nchannels},	{0,NULL}};MSFilterDesc alsa_write_desc={	.id=MS_ALSA_WRITE_ID,	.name="MSAlsaWrite",	.text="Alsa sound output",	.category=MS_FILTER_OTHER,	.ninputs=1,	.noutputs=0,	.init=alsa_write_init,	.process=alsa_write_process,	.postprocess=alsa_write_postprocess,	.uninit=alsa_write_uninit,	.methods=alsa_write_methods};static MSFilter * ms_alsa_write_new(const char *dev){	MSFilter *f=ms_filter_new_from_desc(&alsa_write_desc);	AlsaWriteData *ad=(AlsaWriteData*)f->data;	ad->pcmdev=ms_strdup(dev);	return f;}MS_FILTER_DESC_EXPORT(alsa_write_desc)MS_FILTER_DESC_EXPORT(alsa_read_desc)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -