void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource, int encoding, float sampleRate, int sampleSizeInBits, int frameSize, int channels, int isSigned, int isBigEndian, int bufferSizeInBytes) { snd_pcm_format_mask_t* formatMask; snd_pcm_format_t format; int dir; int ret = 0; AlsaPcmInfo* info = NULL; /* snd_pcm_uframes_t is 64 bit on 64-bit systems */ snd_pcm_uframes_t alsaPeriodSize = 0; snd_pcm_uframes_t alsaBufferSizeInFrames = 0; TRACE0("> DAUDIO_Open\n"); #ifdef USE_TRACE // for using ALSA debug dump methods if (ALSA_OUTPUT == NULL) { snd_output_stdio_attach(&ALSA_OUTPUT, stdout, 0); } #endif info = (AlsaPcmInfo*) malloc(sizeof(AlsaPcmInfo)); if (!info) { ERROR0("Out of memory\n"); return NULL; } memset(info, 0, sizeof(AlsaPcmInfo)); ret = openPCMfromDeviceID(deviceID, &(info->handle), isSource, FALSE /* do open device*/); if (ret == 0) { // set to blocking mode snd_pcm_nonblock(info->handle, 0); ret = snd_pcm_hw_params_malloc(&(info->hwParams)); if (ret != 0) { ERROR1(" snd_pcm_hw_params_malloc returned error %d\n", ret); } else { ret = -1; if (getAlsaFormatFromFormat(&format, frameSize / channels, sampleSizeInBits, isSigned, isBigEndian, encoding)) { if (setHWParams(info, sampleRate, channels, bufferSizeInBytes / frameSize, format)) { info->frameSize = frameSize; #ifdef ALSA_PCM_NEW_HW_PARAMS_API ret = snd_pcm_hw_params_get_period_size(info->hwParams, &alsaPeriodSize, &dir); info->periodSize = (int) alsaPeriodSize; if (ret < 0) { ERROR1("ERROR: snd_pcm_hw_params_get_period: %s\n", snd_strerror(ret)); } snd_pcm_hw_params_get_periods(info->hwParams, &(info->periods), &dir); snd_pcm_hw_params_get_buffer_size(info->hwParams, &alsaBufferSizeInFrames); info->bufferSizeInBytes = (int) alsaBufferSizeInFrames * frameSize; #else info->periodSize = snd_pcm_hw_params_get_period_size(info->hwParams, &dir); info->periods = snd_pcm_hw_params_get_periods(info->hwParams, &dir); info->bufferSizeInBytes = snd_pcm_hw_params_get_buffer_size(info->hwParams) * frameSize; ret = 0; #endif TRACE3(" DAUDIO_Open: period size = %d frames, periods = %d. Buffer size: %d bytes.\n", (int) info->periodSize, info->periods, info->bufferSizeInBytes); } } } if (ret == 0) { // set software parameters ret = snd_pcm_sw_params_malloc(&(info->swParams)); if (ret != 0) { ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret); } else { if (!setSWParams(info)) { ret = -1; } } } if (ret == 0) { // prepare device ret = snd_pcm_prepare(info->handle); if (ret < 0) { ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret)); } } #ifdef GET_POSITION_METHOD2 if (ret == 0) { ret = snd_pcm_status_malloc(&(info->positionStatus)); if (ret != 0) { ERROR1("ERROR in snd_pcm_status_malloc: %s\n", snd_strerror(ret)); } } #endif } if (ret != 0) { DAUDIO_Close((void*) info, isSource); info = NULL; } else { // set to non-blocking mode snd_pcm_nonblock(info->handle, 1); TRACE1("< DAUDIO_Open: Opened device successfully. Handle=%p\n", (void*) info->handle); } return (void*) info; }
void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource, int encoding, float sampleRate, int sampleSizeInBits, int frameSize, int channels, int isSigned, int isBigEndian, int bufferSizeInBytes) { int err = 0; int openMode; AudioDeviceDescription desc; SolPcmInfo* info; TRACE0("> DAUDIO_Open\n"); if (encoding != DAUDIO_PCM) { ERROR1(" DAUDIO_Open: invalid encoding %d\n", (int) encoding); return NULL; } info = (SolPcmInfo*) malloc(sizeof(SolPcmInfo)); if (!info) { ERROR0("Out of memory\n"); return NULL; } memset(info, 0, sizeof(SolPcmInfo)); info->frameSize = frameSize; info->fd = -1; if (isSource) { openMode = O_WRONLY; } else { openMode = O_RDONLY; } #ifndef __linux__ /* blackdown does not use NONBLOCK */ openMode |= O_NONBLOCK; #endif if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) { info->fd = open(desc.path, openMode); } if (info->fd < 0) { ERROR1("Couldn't open audio device for mixer %d!\n", mixerIndex); free(info); return NULL; } /* set to multiple open */ if (ioctl(info->fd, AUDIO_MIXER_MULTIPLE_OPEN, NULL) >= 0) { TRACE1("DAUDIO_Open: %s set to multiple open\n", desc.path); } else { ERROR1("DAUDIO_Open: ioctl AUDIO_MIXER_MULTIPLE_OPEN failed on %s!\n", desc.path); } AUDIO_INITINFO(&(info->info)); /* need AUDIO_GETINFO ioctl to get this to work on solaris x86 */ err = ioctl(info->fd, AUDIO_GETINFO, &(info->info)); /* not valid to call AUDIO_SETINFO ioctl with all the fields from AUDIO_GETINFO. */ AUDIO_INITINFO(&(info->info)); if (isSource) { info->info.play.sample_rate = sampleRate; info->info.play.precision = sampleSizeInBits; info->info.play.channels = channels; info->info.play.encoding = AUDIO_ENCODING_LINEAR; info->info.play.buffer_size = bufferSizeInBytes; info->info.play.pause = 1; } else { info->info.record.sample_rate = sampleRate; info->info.record.precision = sampleSizeInBits; info->info.record.channels = channels; info->info.record.encoding = AUDIO_ENCODING_LINEAR; info->info.record.buffer_size = bufferSizeInBytes; info->info.record.pause = 1; } err = ioctl(info->fd, AUDIO_SETINFO, &(info->info)); if (err < 0) { ERROR0("DAUDIO_Open: could not set info!\n"); DAUDIO_Close((void*) info, isSource); return NULL; } DAUDIO_Flush((void*) info, isSource); err = ioctl(info->fd, AUDIO_GETINFO, &(info->info)); if (err >= 0) { if (isSource) { info->bufferSizeInBytes = info->info.play.buffer_size; } else { info->bufferSizeInBytes = info->info.record.buffer_size; } TRACE2("DAUDIO: buffersize in bytes: requested=%d, got %d\n", (int) bufferSizeInBytes, (int) info->bufferSizeInBytes); } else { ERROR0("DAUDIO_Open: cannot get info!\n"); DAUDIO_Close((void*) info, isSource); return NULL; } TRACE0("< DAUDIO_Open: Opened device successfully.\n"); return (void*) info; }