/** @todo A device framework needs to be introduced to be able to handle
    the different audio devices (configuration etc). For the I/O plugin the
    different audio devices could be defined in .asoundrc. */
static int ste_iop_open(snd_pcm_t **pcmp, const char *name,
                        snd_pcm_stream_t stream, int mode,
                        const char* device_name)
{
    ste_iop_t *ste_iop;
    int err;

    /* Allocate memory for ste_iop. Make sure the struct is zero initialized */
    ste_iop = calloc(1, sizeof(*ste_iop));
    if (ste_iop == NULL) {
        fprintf(stderr,"ST-Ericsson ALSA ADM I/O Plugin: Failed to allocate ste_iop!\n");
        return -ENOMEM;
    }

    /* Initialize IO Plugin struct */
    ste_iop->io.version = SND_PCM_IOPLUG_VERSION;
    ste_iop->io.name = "ST-Ericsson ALSA ADM I/O Plugin";
    ste_iop->io.private_data = ste_iop;
    ste_iop->io.mmap_rw = 0;
    ste_iop->io.stream = stream;
    strncpy(ste_iop->device_name, device_name, 64);
    ste_iop->device_name[63] = 0;

    /* Check if the plugin is opened for playback or capture, and set
        corresponding callback table */
    if (stream == SND_PCM_STREAM_PLAYBACK) {
        ste_iop->io.callback = &ste_iop_playback_callback;
    } else if (stream == SND_PCM_STREAM_CAPTURE) {
        ste_iop->io.callback = &ste_iop_capture_callback;
    } else {
        fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: ERROR! Unknown PCM stream \n");
    }

    /* Create the IO Plugin */
    err = snd_pcm_ioplug_create(&ste_iop->io, name, stream, mode);
    if (err < 0) {
        fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: Failed to create the IO plugin\n");
        return err;
    }

    /* Set HW constraint */
    err = ste_iop_set_hw_constraint(ste_iop);
    if (err < 0) {
        fprintf(stderr, "ST-Ericsson ALSA ADM I/O Plugin: Failed to set HW constraint\n");
        return err;
    }

    /* Update the PCM handle */
    *pcmp = ste_iop->io.pcm;

    return 0;
}
Example #2
0
/* Called by snd_pcm_open().  Creates a CRAS client and an ioplug plugin. */
static int snd_pcm_cras_open(snd_pcm_t **pcmp, const char *name,
			     snd_pcm_stream_t stream, int mode)
{
	struct snd_pcm_cras *pcm_cras;
	int rc;
	int fd[2];

	assert(pcmp);
	pcm_cras = calloc(1, sizeof(*pcm_cras));
	if (!pcm_cras)
		return -ENOMEM;

	pcm_cras->fd = -1;
	pcm_cras->io.poll_fd = -1;
	pcm_cras->channels = 2;
	pcm_cras->direction = (stream == SND_PCM_STREAM_PLAYBACK)
				? CRAS_STREAM_OUTPUT : CRAS_STREAM_INPUT;

	rc = cras_client_create(&pcm_cras->client);
	if (rc != 0 || pcm_cras->client == NULL) {
		fprintf(stderr, "Couldn't create CRAS client\n");
		free(pcm_cras);
		return rc;
	}

	pcm_cras->areas = calloc(pcm_cras->channels,
				 sizeof(snd_pcm_channel_area_t));
	if (pcm_cras->areas == NULL) {
		snd_pcm_cras_free(pcm_cras);
		return -ENOMEM;
	}

	socketpair(AF_LOCAL, SOCK_STREAM, 0, fd);

	cras_make_fd_nonblocking(fd[0]);
	cras_make_fd_nonblocking(fd[1]);

	pcm_cras->fd = fd[0];

	pcm_cras->io.version = SND_PCM_IOPLUG_VERSION;
	pcm_cras->io.name = "ALSA to CRAS Plugin";
	pcm_cras->io.callback = &cras_pcm_callback;
	pcm_cras->io.private_data = pcm_cras;
	pcm_cras->io.poll_fd = fd[1];
	pcm_cras->io.poll_events = POLLIN;
	pcm_cras->io.mmap_rw = 1;

	rc = snd_pcm_ioplug_create(&pcm_cras->io, name, stream, mode);
	if (rc < 0) {
		snd_pcm_cras_free(pcm_cras);
		return rc;
	}

	rc = set_hw_constraints(pcm_cras);
	if (rc < 0) {
		snd_pcm_ioplug_delete(&pcm_cras->io);
		return rc;
	}

	*pcmp = pcm_cras->io.pcm;

	return 0;
}