📄 alsa.c
字号:
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 + -