| /* Copyright 2015 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include <errno.h> |
| #include <stdint.h> |
| #include <sys/param.h> |
| |
| #include "cras_client.h" |
| #include "cras_util.h" |
| |
| struct buffer_data { |
| const uint8_t *buffer; |
| unsigned int offset; |
| unsigned int frame_bytes; |
| unsigned int len; |
| }; |
| |
| static int |
| play_buffer_callback(struct cras_client *client, cras_stream_id_t stream_id, |
| uint8_t *captured_samples, uint8_t *playback_samples, |
| unsigned int frames, const struct timespec *captured_time, |
| const struct timespec *playback_time, void *user_arg) |
| { |
| struct buffer_data *data = (struct buffer_data *)user_arg; |
| int to_copy = data->len - data->offset; |
| |
| if (to_copy <= 0) { |
| free(user_arg); |
| return EOF; |
| } |
| |
| to_copy = MIN(to_copy, frames * data->frame_bytes); |
| |
| memcpy(playback_samples, data->buffer + data->offset, to_copy); |
| |
| data->offset += to_copy; |
| |
| return to_copy / data->frame_bytes; |
| } |
| |
| static int play_buffer_error(struct cras_client *client, |
| cras_stream_id_t stream_id, int error, |
| void *user_arg) |
| { |
| free(user_arg); |
| return 0; |
| } |
| |
| int cras_helper_create_connect_async(struct cras_client **client, |
| cras_connection_status_cb_t connection_cb, |
| void *user_arg) |
| { |
| int rc; |
| |
| rc = cras_client_create(client); |
| if (rc < 0) |
| return rc; |
| |
| cras_client_set_connection_status_cb(*client, connection_cb, user_arg); |
| |
| rc = cras_client_run_thread(*client); |
| if (rc < 0) |
| goto client_start_error; |
| |
| rc = cras_client_connect_async(*client); |
| if (rc < 0) |
| goto client_start_error; |
| |
| return 0; |
| |
| client_start_error: |
| cras_client_destroy(*client); |
| return rc; |
| } |
| |
| int cras_helper_create_connect(struct cras_client **client) |
| { |
| int rc; |
| |
| rc = cras_client_create(client); |
| if (rc < 0) |
| return rc; |
| |
| rc = cras_client_connect(*client); |
| if (rc < 0) |
| goto client_start_error; |
| |
| rc = cras_client_run_thread(*client); |
| if (rc < 0) |
| goto client_start_error; |
| |
| rc = cras_client_connected_wait(*client); |
| if (rc < 0) |
| goto client_start_error; |
| |
| return 0; |
| |
| client_start_error: |
| cras_client_destroy(*client); |
| return rc; |
| } |
| |
| int cras_helper_add_stream_simple( |
| struct cras_client *client, enum CRAS_STREAM_DIRECTION direction, |
| void *user_data, cras_unified_cb_t unified_cb, cras_error_cb_t err_cb, |
| snd_pcm_format_t format, unsigned int frame_rate, |
| unsigned int num_channels, int dev_idx, cras_stream_id_t *stream_id_out) |
| { |
| struct cras_audio_format *aud_format; |
| struct cras_stream_params *params; |
| int rc; |
| |
| aud_format = cras_audio_format_create(format, frame_rate, num_channels); |
| if (!aud_format) |
| return -ENOMEM; |
| |
| params = cras_client_unified_params_create(CRAS_STREAM_OUTPUT, 2048, |
| CRAS_STREAM_TYPE_DEFAULT, 0, |
| user_data, unified_cb, |
| err_cb, aud_format); |
| if (!params) { |
| rc = -ENOMEM; |
| goto done_add_stream; |
| } |
| |
| if (dev_idx < 0) |
| dev_idx = NO_DEVICE; |
| rc = cras_client_add_pinned_stream(client, dev_idx, stream_id_out, |
| params); |
| |
| done_add_stream: |
| cras_audio_format_destroy(aud_format); |
| cras_client_stream_params_destroy(params); |
| return rc; |
| } |
| |
| int cras_helper_play_buffer(struct cras_client *client, const void *buffer, |
| unsigned int frames, snd_pcm_format_t format, |
| unsigned int frame_rate, unsigned int num_channels, |
| int dev_idx) |
| { |
| struct buffer_data *data; |
| cras_stream_id_t stream_id; |
| |
| data = malloc(sizeof(*data)); |
| |
| data->buffer = buffer; |
| data->frame_bytes = num_channels * PCM_FORMAT_WIDTH(format) / 8; |
| data->offset = 0; |
| data->len = frames * data->frame_bytes; |
| |
| return cras_helper_add_stream_simple(client, CRAS_STREAM_OUTPUT, data, |
| play_buffer_callback, |
| play_buffer_error, format, |
| frame_rate, num_channels, dev_idx, |
| &stream_id); |
| } |