📄 winsnd.c
字号:
d->bytes_read=0; d->pcmdev=NULL; d->mixdev=NULL; d->sound_err=-1; /* not opened */ d->read_started=FALSE; d->write_started=FALSE; d->bits=16; d->rate=8000; d->stereo=FALSE; qinit(&d->rq); d->bufferizer=ms_bufferizer_new(); ms_mutex_init(&d->mutex,NULL); card->data=d;#ifndef DISABLE_SPEEX d->pst=0;#endif d->stat_input=0; d->stat_output=0; d->stat_notplayed=0;}static void winsnd_uninit(MSSndCard *card){ WinSndData *d=(WinSndData*)card->data; if (d==NULL) return; if (d->pcmdev!=NULL) ms_free(d->pcmdev); if (d->mixdev!=NULL) ms_free(d->mixdev); ms_bufferizer_destroy(d->bufferizer); flushq(&d->rq,0); ms_mutex_destroy(&d->mutex);#ifndef DISABLE_SPEEX if (d->pst!=NULL) speex_preprocess_state_destroy(d->pst);#endif ms_free(d);}#define DSP_NAME "/dev/dsp"#define MIXER_NAME "/dev/mixer"static void winsnd_detect(MSSndCardManager *m);static MSSndCard *winsnd_dup(MSSndCard *obj);MSSndCardDesc winsnd_card_desc={ "WINSND", winsnd_detect, winsnd_init, winsnd_set_level, winsnd_get_level, winsnd_set_source, ms_winsnd_read_new, ms_winsnd_write_new, winsnd_uninit, winsnd_dup};static MSSndCard *winsnd_dup(MSSndCard *obj){ MSSndCard *card=ms_snd_card_new(&winsnd_card_desc); WinSndData *dcard=(WinSndData*)card->data; WinSndData *dobj=(WinSndData*)obj->data; dcard->pcmdev=ms_strdup(dobj->pcmdev); dcard->mixdev=ms_strdup(dobj->mixdev); dcard->devid=dobj->devid; card->name=ms_strdup(obj->name); return card;}static MSSndCard *winsnd_card_new(const char *pcmdev, const char *mixdev, int id){ MSSndCard *card=ms_snd_card_new(&winsnd_card_desc); WinSndData *d=(WinSndData*)card->data; d->pcmdev=ms_strdup(pcmdev); d->mixdev=ms_strdup(mixdev); card->name=ms_strdup(pcmdev); d->devid=id; return card;}static void winsnd_detect(MSSndCardManager *m){ MMRESULT mr = NOERROR; unsigned int nInDevices = waveInGetNumDevs (); unsigned int item; char pcmdev[1024]; char mixdev[1024]; for (item = 0; item < nInDevices; item++) { WAVEINCAPS caps; mr = waveInGetDevCaps (item, &caps, sizeof (WAVEINCAPS)); if (mr == MMSYSERR_NOERROR) { MSSndCard *card; snprintf(pcmdev,sizeof(pcmdev),"%s",caps.szPname); snprintf(mixdev,sizeof(mixdev),"%s",caps.szPname); if (item == 0) { card=winsnd_card_new(pcmdev,mixdev, item-1); ms_snd_card_manager_add_card(m,card); } card=winsnd_card_new(pcmdev,mixdev, item); ms_snd_card_manager_add_card(m,card); } }#if 0 nInDevices = mixerGetNumDevs (); for (item = 0; item < nInDevices; item++) { MIXERCAPS caps; mr = mixerGetDevCaps (item, &caps, sizeof (MIXERCAPS)); if (mr == MMSYSERR_NOERROR) { snprintf(pcmdev,sizeof(pcmdev),"%s",caps.szPname); snprintf(mixdev,sizeof(mixdev),"%s",caps.szPname); } }#endif}static void * winsnd_thread(void *p){ MSSndCard *card=(MSSndCard*)p; WinSndData *d=(WinSndData*)card->data; int bsize=d->rate/8000 * 320; uint8_t *rtmpbuff=NULL; uint8_t *wtmpbuff=NULL; int err; MMRESULT mr = NOERROR; int pos_whdr=0; d->stat_input=0; d->stat_output=0; d->stat_notplayed=0; d->sound_err=winsnd_open(d, d->devid, d->bits,d->stereo,d->rate,&bsize); if (d->sound_err==0){ rtmpbuff=(uint8_t*)alloca(bsize); wtmpbuff=(uint8_t*)alloca(bsize); } while(d->read_started || d->write_started){ if (d->sound_err==0){ if (d->write_started){#if 0 if (d->stat_output>0 && d->buffer_playing==0) { ms_error("No data currently playing in sound card" ); } if (d->stat_output>0 && (d->stat_input-d->stat_output>10 || d->stat_input-d->stat_output<-10)) ms_error("Not perfectly synchronized (input-output=%i)", d->stat_input-d->stat_output);#endif while (d->buffer_playing<6 && d->buffer_playing<MAX_WAVEHDR) { ms_mutex_lock(&d->mutex); err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize); ms_mutex_unlock(&d->mutex); if (err!=bsize) break; ms_mutex_lock(&d->mutex); /* write to sound devide! */ memcpy (d->waveouthdr[pos_whdr].lpData, wtmpbuff, bsize); mr = waveOutWrite (d->waveoutdev, &(d->waveouthdr[pos_whdr]), sizeof (d->waveouthdr[pos_whdr])); if (mr != MMSYSERR_NOERROR) { if (mr == WAVERR_STILLPLAYING) { /* retry later */ /* data should go back to queue */ /* TODO */ ms_warning("sound device write STILL_PLAYING (waveOutWrite:0x%i)", mr); } else { ms_warning("sound device write returned (waveOutWrite:0x%i)", mr); } } else { d->buffer_playing++; pos_whdr++; if (pos_whdr == MAX_WAVEHDR) pos_whdr = 0; /* loop over the prepared blocks */ } ms_mutex_unlock(&d->mutex); if (err<0){#if !defined(_WIN32_WCE) ms_warning("Fail to write %i bytes from soundcard: %s", bsize,strerror(errno));#else ms_warning("Fail to write %i bytes from soundcard: %i", bsize,WSAGetLastError());#endif } } if (d->buffer_playing==6 || d->buffer_playing==MAX_WAVEHDR) { int discarded=0; ms_mutex_lock(&d->mutex); while (d->bufferizer->size>=bsize){ discarded++; d->stat_notplayed++; err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize); } ms_mutex_unlock(&d->mutex); if (discarded>0) ms_error("Extra data for sound card removed (%ims), (playing: %i) (input-output: %i)", (discarded*20*320)/320, d->buffer_playing, d->stat_input - d->stat_output); }#if !defined(_WIN32_WCE) Sleep(5);#endif#if defined(_WIN32_WCE) Sleep(10);#endif }else { int discarded=0; /* don't think this is usefull, anyway... */ ms_mutex_lock(&d->mutex); while (d->bufferizer->size>=bsize){ discarded++; err=ms_bufferizer_read(d->bufferizer,wtmpbuff,bsize); } ms_mutex_unlock(&d->mutex); if (discarded>0) ms_error("Extra data for sound card removed (%ims), (playing: %i) (input-output: %i)", (discarded*20)/320, d->buffer_playing, d->stat_input - d->stat_output); Sleep(10); } }else Sleep(10); } if (d->sound_err==0) { int i; int count=0; /* close sound card */ ms_error("Shutting down sound device (playing: %i) (input-output: %i) (notplayed: %i)", d->buffer_playing, d->stat_input - d->stat_output, d->stat_notplayed); /* unprepare buffer */ for (i = 0; i < MAX_WAVEHDR; i++) { int counttry=0; for (counttry=0;counttry<10;counttry++) { mr = waveInUnprepareHeader (d->waveindev, &(d->waveinhdr[i]), sizeof (d->waveinhdr[i])); if (mr != MMSYSERR_NOERROR) { ms_error("Failed to unprepared %i buffer from sound card (waveInUnprepareHeader:0x%i", count, mr); Sleep (20); } else { count++; ms_message("successfully unprepared %i buffer from sound card.", count); break; } } } ms_warning("unprepared %i buffer from sound card.", count); mr = waveInStop (d->waveindev); if (mr != MMSYSERR_NOERROR) { ms_error("failed to stop recording sound card (waveInStop:0x%i)", mr); } else { ms_message("successfully stopped recording sound card"); } mr = waveInReset (d->waveindev); if (mr != MMSYSERR_NOERROR) { ms_warning("failed to reset recording sound card (waveInReset:0x%i)", mr); } else { ms_message("successful reset of recording sound card"); } mr = waveInClose (d->waveindev); if (mr != MMSYSERR_NOERROR) { ms_warning("failed to close recording sound card (waveInClose:0x%i)", mr); } else { ms_message("successfully closed recording sound card"); } d->sound_err=-1; } d->stat_input=0; d->stat_output=0; d->stat_notplayed=0; return NULL;}static void winsnd_start_r(MSSndCard *card){ WinSndData *d=(WinSndData*)card->data; if (d->read_started==FALSE && d->write_started==FALSE){ d->read_started=TRUE; ms_thread_create(&d->thread,NULL,winsnd_thread,card); }else d->read_started=TRUE;}static void winsnd_stop_r(MSSndCard *card){ WinSndData *d=(WinSndData*)card->data; d->read_started=FALSE; if (d->write_started==FALSE){ ms_thread_join(d->thread,NULL); }}static void winsnd_start_w(MSSndCard *card){ WinSndData *d=(WinSndData*)card->data; if (d->read_started==FALSE && d->write_started==FALSE){ d->write_started=TRUE; ms_thread_create(&d->thread,NULL,winsnd_thread,card); }else{ d->write_started=TRUE; }}static void winsnd_stop_w(MSSndCard *card){ WinSndData *d=(WinSndData*)card->data; d->write_started=FALSE; if (d->read_started==FALSE){ ms_thread_join(d->thread,NULL); }#ifdef CONTROLVOLUME waveOutSetVolume(d->waveoutdev, d->dwOldVolume);#endif}static mblk_t *winsnd_get(MSSndCard *card){ WinSndData *d=(WinSndData*)card->data; mblk_t *m; ms_mutex_lock(&d->mutex); m=getq(&d->rq); ms_mutex_unlock(&d->mutex); return m;}static void winsnd_put(MSSndCard *card, mblk_t *m){ WinSndData *d=(WinSndData*)card->data; ms_mutex_lock(&d->mutex); ms_bufferizer_put(d->bufferizer,m); ms_mutex_unlock(&d->mutex);}static void winsnd_read_preprocess(MSFilter *f){ MSSndCard *card=(MSSndCard*)f->data; winsnd_start_r(card); ms_ticker_set_time_func(f->ticker,winsnd_get_cur_time,card->data);}static void winsnd_read_postprocess(MSFilter *f){ MSSndCard *card=(MSSndCard*)f->data; ms_ticker_set_time_func(f->ticker,NULL,NULL); winsnd_stop_r(card);}static void winsnd_read_process(MSFilter *f){ MSSndCard *card=(MSSndCard*)f->data; mblk_t *m; while((m=winsnd_get(card))!=NULL){ ms_queue_put(f->outputs[0],m); }}static void winsnd_write_preprocess(MSFilter *f){ MSSndCard *card=(MSSndCard*)f->data; winsnd_start_w(card);}static void winsnd_write_postprocess(MSFilter *f){ MSSndCard *card=(MSSndCard*)f->data; winsnd_stop_w(card);}static void winsnd_write_process(MSFilter *f){ MSSndCard *card=(MSSndCard*)f->data; mblk_t *m; while((m=ms_queue_get(f->inputs[0]))!=NULL){ winsnd_put(card,m); }}static int set_rate(MSFilter *f, void *arg){ MSSndCard *card=(MSSndCard*)f->data; WinSndData *d=(WinSndData*)card->data; d->rate=*((int*)arg); return 0;}static int set_nchannels(MSFilter *f, void *arg){ MSSndCard *card=(MSSndCard*)f->data; WinSndData *d=(WinSndData*)card->data; d->stereo=(*((int*)arg)==2); return 0;}static int winsnd_get_stat_input(MSFilter *f, void *arg){ MSSndCard *card=(MSSndCard*)f->data; WinSndData *d=(WinSndData*)card->data; return d->stat_input;}static int winsnd_get_stat_ouptut(MSFilter *f, void *arg){ MSSndCard *card=(MSSndCard*)f->data; WinSndData *d=(WinSndData*)card->data; return d->stat_output;}static int winsnd_get_stat_discarded(MSFilter *f, void *arg){ MSSndCard *card=(MSSndCard*)f->data; WinSndData *d=(WinSndData*)card->data; return d->stat_notplayed;}static MSFilterMethod winsnd_methods[]={ { MS_FILTER_SET_SAMPLE_RATE , set_rate }, { MS_FILTER_SET_NCHANNELS , set_nchannels }, { MS_FILTER_GET_STAT_INPUT, winsnd_get_stat_input }, { MS_FILTER_GET_STAT_OUTPUT, winsnd_get_stat_ouptut }, { MS_FILTER_GET_STAT_DISCARDED, winsnd_get_stat_discarded }, { 0 , NULL }};MSFilterDesc winsnd_read_desc={ MS_WINSND_READ_ID, "MSWinSndRead", "Sound capture filter for Windows Sound drivers", MS_FILTER_OTHER, NULL, 0, 1, NULL, winsnd_read_preprocess, winsnd_read_process, winsnd_read_postprocess, NULL, winsnd_methods};MSFilterDesc winsnd_write_desc={ MS_WINSND_WRITE_ID, "MSWinSndWrite", "Sound playback filter for Windows Sound drivers", MS_FILTER_OTHER, NULL, 1, 0, NULL, winsnd_write_preprocess, winsnd_write_process, winsnd_write_postprocess, NULL, winsnd_methods};MSFilter *ms_winsnd_read_new(MSSndCard *card){ MSFilter *f=ms_filter_new_from_desc(&winsnd_read_desc); f->data=card; return f;}MSFilter *ms_winsnd_write_new(MSSndCard *card){ MSFilter *f=ms_filter_new_from_desc(&winsnd_write_desc); f->data=card; return f;}MS_FILTER_DESC_EXPORT(winsnd_read_desc)MS_FILTER_DESC_EXPORT(winsnd_write_desc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -