/** @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; }
/* 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; }