• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,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)21 play_buffer_callback(struct cras_client *client, cras_stream_id_t stream_id,
22 		     uint8_t *captured_samples, uint8_t *playback_samples,
23 		     unsigned int frames, const struct timespec *captured_time,
24 		     const struct timespec *playback_time, void *user_arg)
25 {
26 	struct buffer_data *data = (struct buffer_data *)user_arg;
27 	int to_copy = data->len - data->offset;
28 
29 	if (to_copy <= 0) {
30 		free(user_arg);
31 		return EOF;
32 	}
33 
34 	to_copy = MIN(to_copy, frames * data->frame_bytes);
35 
36 	memcpy(playback_samples, data->buffer + data->offset, to_copy);
37 
38 	data->offset += to_copy;
39 
40 	return to_copy / data->frame_bytes;
41 }
42 
play_buffer_error(struct cras_client * client,cras_stream_id_t stream_id,int error,void * user_arg)43 static int play_buffer_error(struct cras_client *client,
44 			     cras_stream_id_t stream_id, int error,
45 			     void *user_arg)
46 {
47 	free(user_arg);
48 	return 0;
49 }
50 
cras_helper_create_connect_async(struct cras_client ** client,cras_connection_status_cb_t connection_cb,void * user_arg)51 int cras_helper_create_connect_async(struct cras_client **client,
52 				     cras_connection_status_cb_t connection_cb,
53 				     void *user_arg)
54 {
55 	int rc;
56 
57 	rc = cras_client_create(client);
58 	if (rc < 0)
59 		return rc;
60 
61 	cras_client_set_connection_status_cb(*client, connection_cb, user_arg);
62 
63 	rc = cras_client_run_thread(*client);
64 	if (rc < 0)
65 		goto client_start_error;
66 
67 	rc = cras_client_connect_async(*client);
68 	if (rc < 0)
69 		goto client_start_error;
70 
71 	return 0;
72 
73 client_start_error:
74 	cras_client_destroy(*client);
75 	return rc;
76 }
77 
cras_helper_create_connect(struct cras_client ** client)78 int cras_helper_create_connect(struct cras_client **client)
79 {
80 	int rc;
81 
82 	rc = cras_client_create(client);
83 	if (rc < 0)
84 		return rc;
85 
86 	rc = cras_client_connect(*client);
87 	if (rc < 0)
88 		goto client_start_error;
89 
90 	rc = cras_client_run_thread(*client);
91 	if (rc < 0)
92 		goto client_start_error;
93 
94 	rc = cras_client_connected_wait(*client);
95 	if (rc < 0)
96 		goto client_start_error;
97 
98 	return 0;
99 
100 client_start_error:
101 	cras_client_destroy(*client);
102 	return rc;
103 }
104 
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)105 int cras_helper_add_stream_simple(
106 	struct cras_client *client, enum CRAS_STREAM_DIRECTION direction,
107 	void *user_data, cras_unified_cb_t unified_cb, cras_error_cb_t err_cb,
108 	snd_pcm_format_t format, unsigned int frame_rate,
109 	unsigned int num_channels, int dev_idx, cras_stream_id_t *stream_id_out)
110 {
111 	struct cras_audio_format *aud_format;
112 	struct cras_stream_params *params;
113 	int rc;
114 
115 	aud_format = cras_audio_format_create(format, frame_rate, num_channels);
116 	if (!aud_format)
117 		return -ENOMEM;
118 
119 	params = cras_client_unified_params_create(CRAS_STREAM_OUTPUT, 2048,
120 						   CRAS_STREAM_TYPE_DEFAULT, 0,
121 						   user_data, unified_cb,
122 						   err_cb, aud_format);
123 	if (!params) {
124 		rc = -ENOMEM;
125 		goto done_add_stream;
126 	}
127 
128 	if (dev_idx < 0)
129 		dev_idx = NO_DEVICE;
130 	rc = cras_client_add_pinned_stream(client, dev_idx, stream_id_out,
131 					   params);
132 
133 done_add_stream:
134 	cras_audio_format_destroy(aud_format);
135 	cras_client_stream_params_destroy(params);
136 	return rc;
137 }
138 
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)139 int cras_helper_play_buffer(struct cras_client *client, const void *buffer,
140 			    unsigned int frames, snd_pcm_format_t format,
141 			    unsigned int frame_rate, unsigned int num_channels,
142 			    int dev_idx)
143 {
144 	struct buffer_data *data;
145 	cras_stream_id_t stream_id;
146 
147 	data = malloc(sizeof(*data));
148 
149 	data->buffer = buffer;
150 	data->frame_bytes = num_channels * PCM_FORMAT_WIDTH(format) / 8;
151 	data->offset = 0;
152 	data->len = frames * data->frame_bytes;
153 
154 	return cras_helper_add_stream_simple(client, CRAS_STREAM_OUTPUT, data,
155 					     play_buffer_callback,
156 					     play_buffer_error, format,
157 					     frame_rate, num_channels, dev_idx,
158 					     &stream_id);
159 }
160