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;
}
Beispiel #2
0
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;
}