📄 alsa.c
字号:
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); //ms_message("Successfully 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); //ms_message("Successfully 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); //ms_message("Successfully set capture switch for %s.",elemname); } break; } } elem=snd_mixer_elem_next(elem); } return ;}static void alsa_card_set_level(MSSndCard *obj,MSSndCardMixerElem e,int a){ snd_mixer_t *mixer; AlsaData *ad=(AlsaData*)obj->data; mixer=alsa_mixer_open(ad->mixdev); if (mixer==NULL) return ; switch(e){ case MS_SND_CARD_MASTER: set_mixer_element(mixer,"Master",a,PLAYBACK); break; case MS_SND_CARD_CAPTURE: set_mixer_element(mixer,"Capture",a,CAPTURE); break; case MS_SND_CARD_PLAYBACK: set_mixer_element(mixer,"PCM",a,PLAYBACK); break; default: ms_warning("alsa_card_set_level: unsupported command."); } alsa_mixer_close(mixer);}static int alsa_card_get_level(MSSndCard *obj, MSSndCardMixerElem e){ snd_mixer_t *mixer; AlsaData *ad=(AlsaData*)obj->data; int value = -1; mixer=alsa_mixer_open(ad->mixdev); if (mixer==NULL) return 0; switch(e){ case MS_SND_CARD_MASTER: value=get_mixer_element(mixer,"Master",PLAYBACK); break; 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);}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;};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;}void alsa_read_postprocess(MSFilter *obj){ AlsaReadData *ad=(AlsaReadData*)obj->data; if (ad->handle!=NULL) snd_pcm_close(ad->handle); ad->handle=NULL;}void alsa_read_uninit(MSFilter *obj){ AlsaReadData *ad=(AlsaReadData*)obj->data; if (ad->pcmdev!=NULL) ms_free(ad->pcmdev); if (ad->handle!=NULL) snd_pcm_close(ad->handle); ms_free(ad);}void alsa_read_process(MSFilter *obj){ AlsaReadData *ad=(AlsaReadData*)obj->data;#ifdef AMD_HACK int samples=(160*ad->rate)/8000;#else int samples=(128*ad->rate)/8000;#endif 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)){ 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);#ifdef AMD_HACK break;#endif }}static 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, .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 + -