static ALCuint qsa_available_samples(ALCdevice* device) { qsa_data* data=(qsa_data*)device->ExtraData; snd_pcm_channel_status_t status; ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType); ALint free_size; int rstatus; memset(&status, 0, sizeof (status)); status.channel=SND_PCM_CHANNEL_CAPTURE; snd_pcm_plugin_status(data->pcmHandle, &status); if ((status.status==SND_PCM_STATUS_OVERRUN) || (status.status==SND_PCM_STATUS_READY)) { if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) { ERR("capture prepare failed: %s\n", snd_strerror(rstatus)); aluHandleDisconnect(device); return 0; } snd_pcm_capture_go(data->pcmHandle); return 0; } free_size=data->csetup.buf.block.frag_size*data->csetup.buf.block.frags; free_size-=status.free; return free_size/frame_size; }
static void qsa_start_capture(ALCdevice* device) { qsa_data* data=(qsa_data*)device->ExtraData; int rstatus; if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) { ERR("capture prepare failed: %s\n", snd_strerror(rstatus)); return; } memset(&data->csetup, 0, sizeof(data->csetup)); data->csetup.channel=SND_PCM_CHANNEL_CAPTURE; if ((rstatus=snd_pcm_plugin_setup(data->pcmHandle, &data->csetup))<0) { ERR("capture setup failed: %s\n", snd_strerror(rstatus)); return; } snd_pcm_capture_go(data->pcmHandle); }
static int voice_test() { int rtn = 0; char* name; fd_set rfds, wfds; Audio_t hPcm_Mic; Audio_t hPcm_Spk; snd_pcm_channel_params_t params; bool bQuit = false; /************************ CAPTURE **************************/ // configuring capture (mic) name = "voice"; // get audioman handle rtn = audio_manager_get_handle(AUDIO_TYPE_VIDEO_CHAT, getpid(), (bool)false, &hPcm_Mic.hAudioman); if(rtn < 0) { cli_print("audio_manager_get_handle (mic) failed %s", strerror(-rtn)); return -1; } cli_print("Opening %s - for capture", name); rtn = snd_pcm_open_name(&hPcm_Mic.pDs, name, SND_PCM_OPEN_CAPTURE); if (rtn < 0) { (void)audio_manager_free_handle(hPcm_Mic.hAudioman); cli_print("snd_pcm_open_name (mic) failed %s", snd_strerror(rtn)); return -1; // snd_pcm calls return negative values; make positive } rtn = snd_pcm_set_audioman_handle(hPcm_Mic.pDs, hPcm_Mic.hAudioman); if (rtn < 0) { (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); cli_print("snd_pcm_set_audioman_handle (mic) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); return -1; } // disable mmap (void)snd_pcm_plugin_set_disable(hPcm_Mic.pDs, (unsigned int)PLUGIN_DISABLE_MMAP); // set parameters memset(¶ms, 0, sizeof(params)); params.mode = SND_PCM_MODE_BLOCK; params.channel = SND_PCM_CHANNEL_CAPTURE; params.start_mode = SND_PCM_START_GO; params.stop_mode = SND_PCM_STOP_ROLLOVER; params.buf.block.frag_size = fragsize; params.buf.block.frags_max = 1; params.buf.block.frags_min = 1; params.format.rate = 8000; //samplerate; params.format.interleave = 1; params.format.voices = channels; params.format.format = SND_PCM_SFMT_S16_LE; rtn = snd_pcm_plugin_params(hPcm_Mic.pDs, ¶ms); if (rtn < 0) { cli_print("snd_pcm_plugin_params (mic) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); return -1; } // get file descriptor for use with the select() call hPcm_Mic.hFD = snd_pcm_file_descriptor(hPcm_Mic.pDs, SND_PCM_CHANNEL_CAPTURE); if (hPcm_Mic.hFD < 0) { cli_print("snd_pcm_file_descriptor (mic) failed %s", snd_strerror(hPcm_Mic.hFD)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); return -1; } // Signal the driver to ready the capture channel rtn = snd_pcm_plugin_prepare(hPcm_Mic.pDs, SND_PCM_CHANNEL_CAPTURE); if (rtn < 0) { cli_print("snd_pcm_plugin_prepare (mic) failed %s", snd_strerror(errno)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); return -1; } fragsize = params.buf.block.frag_size; /************************ PLAYBACK **************************/ name = "voice"; // get and set audioman handle rtn = audio_manager_get_handle(AUDIO_TYPE_VIDEO_CHAT, getpid(), (bool)false, &hPcm_Spk.hAudioman); if (rtn < 0) { cli_print("audioman audio_manager_get_handle (spk) failed %s", strerror(-rtn) ); (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); return -1; } #ifdef HANDSET // set audio manager handle type rtn = audio_manager_set_handle_type(hPcm_Spk.hAudioman, AUDIO_TYPE_VIDEO_CHAT, device_type, device_type); if (rtn < 0) { (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); cli_print("audio_manager_set_handle_type (spk) failed %s", strerror(-rtn)); return -1; } #endif // Create a handle and open a connection to an audio interface specified by name cli_print("Opening %s - for playback", name); rtn = snd_pcm_open_name(&hPcm_Spk.pDs, name, SND_PCM_OPEN_PLAYBACK); if (rtn < 0) { cli_print("snd_pcm_open_name (spk) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } rtn = snd_pcm_set_audioman_handle(hPcm_Spk.pDs, hPcm_Spk.hAudioman); if (rtn < 0) { cli_print("snd_pcm_set_audioman_handle (spk) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)snd_pcm_close(hPcm_Spk.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } // disable mmap (void)snd_pcm_plugin_set_disable(hPcm_Spk.pDs, (unsigned int)PLUGIN_DISABLE_MMAP); // set parameters memset(¶ms, 0, sizeof(params)); params.mode = SND_PCM_MODE_BLOCK; params.channel = SND_PCM_CHANNEL_PLAYBACK; params.start_mode = SND_PCM_START_GO; params.stop_mode = SND_PCM_STOP_ROLLOVER; params.buf.block.frag_size = fragsize; params.buf.block.frags_max = 1; params.buf.block.frags_min = 1; params.format.rate = samplerate; params.format.interleave = 1; params.format.voices = channels; params.format.format = SND_PCM_SFMT_S16_LE; // Set the configurable parameters for a PCM channel rtn = snd_pcm_plugin_params(hPcm_Spk.pDs, ¶ms); if (rtn < 0) { cli_print("snd_pcm_plugin_params (spk) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)snd_pcm_close(hPcm_Spk.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } // get file descriptor for use with the select() call hPcm_Spk.hFD = snd_pcm_file_descriptor(hPcm_Spk.pDs, SND_PCM_CHANNEL_PLAYBACK); if (hPcm_Spk.hFD < 0) { cli_print("snd_pcm_file_descriptor (spk) failed %s", snd_strerror(hPcm_Spk.hFD)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)snd_pcm_close(hPcm_Spk.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } // Signal the driver to ready the playback channel rtn = snd_pcm_plugin_prepare(hPcm_Spk.pDs, SND_PCM_CHANNEL_PLAYBACK); if (rtn < 0) { cli_print("snd_pcm_plugin_prepare (spk) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)snd_pcm_close(hPcm_Spk.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } fragsize = params.buf.block.frag_size; rtn = snd_pcm_capture_go(hPcm_Mic.pDs); if( rtn < 0) { cli_print("snd_pcm_capture_go (mic) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)snd_pcm_close(hPcm_Spk.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } rtn = snd_pcm_playback_go(hPcm_Spk.pDs); if (rtn < 0) { cli_print("snd_pcm_playback_go (spk) failed %s", snd_strerror(rtn)); (void)snd_pcm_close(hPcm_Mic.pDs); (void)snd_pcm_close(hPcm_Spk.pDs); (void)audio_manager_free_handle(hPcm_Mic.hAudioman); (void)audio_manager_free_handle(hPcm_Spk.hAudioman); return -1; } /******************* PLAYBACK/RECORD LOOP **************************/ while(!bQuit) { int width; struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 350000; // 350 ms FD_ZERO(&rfds); FD_ZERO(&wfds); FD_SET(hPcm_Mic.hFD, &rfds); FD_SET(hPcm_Spk.hFD, &wfds); width = ((hPcm_Spk.hFD > hPcm_Mic.hFD) ? hPcm_Spk.hFD : hPcm_Mic.hFD) + 1; rtn = select(width, &rfds, &wfds, NULL, &timeout); if (rtn > 0) { if (FD_ISSET(hPcm_Spk.hFD, &wfds)) { bQuit = process_write(hPcm_Spk.pDs); } if (FD_ISSET(hPcm_Mic.hFD, &rfds)) { bQuit = process_read(hPcm_Mic.pDs); } } else if (rtn == 0){ cli_print("select: timed out"); bQuit = true; } else { // (rtn < 0) cli_print("select: %s", strerror(errno)); bQuit = true; } } // Ensure audio processing is stopped if ((rtn = snd_pcm_plugin_playback_drain(hPcm_Spk.pDs)) < 0) { cli_print("snd_pcm_plugin_playback_drain (spk) failed %s", snd_strerror(rtn)); } if ((rtn = snd_pcm_plugin_flush(hPcm_Mic.pDs, SND_PCM_CHANNEL_CAPTURE)) < 0) { cli_print("snd_pcm_plugin_flush (mic) failed %s", snd_strerror(rtn)); } if ((rtn = snd_pcm_close(hPcm_Spk.pDs)) < 0) { cli_print("snd_pcm_close (spk) failed %s", snd_strerror(rtn)); } if ((rtn = snd_pcm_close(hPcm_Mic.pDs)) < 0) { cli_print("snd_pcm_close (mic) failed %s", snd_strerror(rtn)); } if (hPcm_Spk.hAudioman) { (void)audio_manager_free_handle(hPcm_Spk.hAudioman); } if (hPcm_Mic.hAudioman) { (void)audio_manager_free_handle(hPcm_Mic.hAudioman); } return 0; }
static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) { qsa_data* data=(qsa_data*)device->ExtraData; char* read_ptr; snd_pcm_channel_status_t status; fd_set rfds; int selectret; struct timeval timeout; int bytes_read; ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType); ALint len=samples*frame_size; int rstatus; read_ptr=buffer; while (len>0) { FD_ZERO(&rfds); FD_SET(data->audio_fd, &rfds); timeout.tv_sec=2; timeout.tv_usec=0; /* Select also works like time slice to OS */ bytes_read=0; selectret=select(data->audio_fd+1, &rfds, NULL, NULL, &timeout); switch (selectret) { case -1: aluHandleDisconnect(device); return ALC_INVALID_DEVICE; case 0: break; default: if (FD_ISSET(data->audio_fd, &rfds)) { bytes_read=snd_pcm_plugin_read(data->pcmHandle, read_ptr, len); break; } break; } if (bytes_read<=0) { if ((errno==EAGAIN) || (errno==EWOULDBLOCK)) { continue; } memset(&status, 0, sizeof (status)); status.channel=SND_PCM_CHANNEL_CAPTURE; snd_pcm_plugin_status(data->pcmHandle, &status); /* we need to reinitialize the sound channel if we've overrun the buffer */ if ((status.status==SND_PCM_STATUS_OVERRUN) || (status.status==SND_PCM_STATUS_READY)) { if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) { ERR("capture prepare failed: %s\n", snd_strerror(rstatus)); aluHandleDisconnect(device); return ALC_INVALID_DEVICE; } snd_pcm_capture_go(data->pcmHandle); } } else { read_ptr+=bytes_read; len-=bytes_read; } } return ALC_NO_ERROR; }