1 /* Copyright 2015 The Chromium OS Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 */ 5 6 #include <errno.h> 7 #include <stdint.h> 8 #include <sys/param.h> 9 10 #include "cras_client.h" 11 #include "cras_util.h" 12 13 struct buffer_data { 14 const uint8_t *buffer; 15 unsigned int offset; 16 unsigned int frame_bytes; 17 unsigned int len; 18 }; 19 20 static int play_buffer_callback(struct cras_client *client, 21 cras_stream_id_t stream_id, 22 uint8_t *captured_samples, 23 uint8_t *playback_samples, 24 unsigned int frames, 25 const struct timespec *captured_time, 26 const struct timespec *playback_time, 27 void *user_arg) 28 { 29 struct buffer_data *data = (struct buffer_data *)user_arg; 30 int to_copy = data->len - data->offset; 31 32 if (to_copy <= 0) { 33 free(user_arg); 34 return EOF; 35 } 36 37 to_copy = MIN(to_copy, frames * data->frame_bytes); 38 39 memcpy(playback_samples, data->buffer + data->offset, to_copy); 40 41 data->offset += to_copy; 42 43 return to_copy / data->frame_bytes; 44 } 45 46 static int play_buffer_error(struct cras_client *client, 47 cras_stream_id_t stream_id, 48 int error, 49 void *user_arg) 50 { 51 free(user_arg); 52 return 0; 53 } 54 55 int cras_helper_create_connect_async(struct cras_client **client, 56 cras_connection_status_cb_t connection_cb, 57 void *user_arg) 58 { 59 int rc; 60 61 rc = cras_client_create(client); 62 if (rc < 0) 63 return rc; 64 65 cras_client_set_connection_status_cb(*client, connection_cb, user_arg); 66 67 rc = cras_client_run_thread(*client); 68 if (rc < 0) 69 goto client_start_error; 70 71 rc = cras_client_connect_async(*client); 72 if (rc < 0) 73 goto client_start_error; 74 75 return 0; 76 77 client_start_error: 78 cras_client_destroy(*client); 79 return rc; 80 } 81 82 int cras_helper_create_connect(struct cras_client **client) 83 { 84 int rc; 85 86 rc = cras_client_create(client); 87 if (rc < 0) 88 return rc; 89 90 rc = cras_client_connect(*client); 91 if (rc < 0) 92 goto client_start_error; 93 94 rc = cras_client_run_thread(*client); 95 if (rc < 0) 96 goto client_start_error; 97 98 rc = cras_client_connected_wait(*client); 99 if (rc < 0) 100 goto client_start_error; 101 102 return 0; 103 104 client_start_error: 105 cras_client_destroy(*client); 106 return rc; 107 } 108 109 int cras_helper_add_stream_simple(struct cras_client *client, 110 enum CRAS_STREAM_DIRECTION direction, 111 void *user_data, 112 cras_unified_cb_t unified_cb, 113 cras_error_cb_t err_cb, 114 snd_pcm_format_t format, 115 unsigned int frame_rate, 116 unsigned int num_channels, 117 int dev_idx, 118 cras_stream_id_t *stream_id_out) 119 { 120 struct cras_audio_format *aud_format; 121 struct cras_stream_params *params; 122 int rc; 123 124 aud_format = cras_audio_format_create(format, frame_rate, num_channels); 125 if (!aud_format) 126 return -ENOMEM; 127 128 params = cras_client_unified_params_create(CRAS_STREAM_OUTPUT, 129 2048, CRAS_STREAM_TYPE_DEFAULT, 0, user_data, 130 unified_cb, err_cb, aud_format); 131 if (!params) { 132 rc = -ENOMEM; 133 goto done_add_stream; 134 } 135 136 if (dev_idx < 0) 137 dev_idx = NO_DEVICE; 138 rc = cras_client_add_pinned_stream(client, dev_idx, stream_id_out, 139 params); 140 141 done_add_stream: 142 cras_audio_format_destroy(aud_format); 143 cras_client_stream_params_destroy(params); 144 return rc; 145 } 146 147 int cras_helper_play_buffer(struct cras_client *client, 148 const void *buffer, 149 unsigned int frames, 150 snd_pcm_format_t format, 151 unsigned int frame_rate, 152 unsigned int num_channels, 153 int dev_idx) 154 { 155 struct buffer_data *data; 156 cras_stream_id_t stream_id; 157 158 data = malloc(sizeof(*data)); 159 160 data->buffer = buffer; 161 data->frame_bytes = num_channels * PCM_FORMAT_WIDTH(format) / 8; 162 data->offset = 0; 163 data->len = frames * data->frame_bytes; 164 165 return cras_helper_add_stream_simple(client, CRAS_STREAM_OUTPUT, data, 166 play_buffer_callback, play_buffer_error, format, 167 frame_rate, num_channels, dev_idx, &stream_id); 168 } 169