1 /* Copyright (c) 2012 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 <pthread.h>
7 #include <sys/param.h>
8 #include <syslog.h>
9
10 #include "cras_audio_area.h"
11 #include "cras_config.h"
12 #include "cras_iodev.h"
13 #include "cras_iodev_list.h"
14 #include "cras_rstream.h"
15 #include "cras_types.h"
16 #include "utlist.h"
17
18 #define EMPTY_BUFFER_SIZE (16 * 1024)
19 #define EMPTY_FRAME_SIZE 4
20 #define EMPTY_FRAMES (EMPTY_BUFFER_SIZE / EMPTY_FRAME_SIZE)
21
22 static size_t empty_supported_rates[] = {
23 44100, 48000, 0
24 };
25
26 static size_t empty_supported_channel_counts[] = {
27 1, 2, 0
28 };
29
30 static snd_pcm_format_t empty_supported_formats[] = {
31 SND_PCM_FORMAT_S16_LE,
32 SND_PCM_FORMAT_S24_LE,
33 SND_PCM_FORMAT_S32_LE,
34 SND_PCM_FORMAT_S24_3LE,
35 0
36 };
37
38 struct empty_iodev {
39 struct cras_iodev base;
40 int open;
41 uint8_t *audio_buffer;
42 unsigned int buffer_level;
43 struct timespec last_buffer_access;
44 };
45
46 /* Current level of the audio buffer. This is made up based on what has been
47 * read/written and how long it has been since then. Simulates audio hardware
48 * running at the given sample rate.
49 */
current_level(const struct cras_iodev * iodev)50 static unsigned int current_level(const struct cras_iodev *iodev)
51 {
52 struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
53 unsigned int frames, frames_since_last;
54
55 if (iodev->active_node->type == CRAS_NODE_TYPE_HOTWORD)
56 return 0;
57
58 frames = empty_iodev->buffer_level;
59 frames_since_last = cras_frames_since_time(
60 &empty_iodev->last_buffer_access,
61 iodev->format->frame_rate);
62
63 if (iodev->direction == CRAS_STREAM_INPUT)
64 return (frames + frames_since_last) % EMPTY_FRAMES;
65
66 /* output */
67 if (frames <= frames_since_last)
68 return 0;
69 return frames - frames_since_last;
70 }
71
72 /*
73 * iodev callbacks.
74 */
75
frames_queued(const struct cras_iodev * iodev,struct timespec * tstamp)76 static int frames_queued(const struct cras_iodev *iodev,
77 struct timespec *tstamp)
78 {
79 clock_gettime(CLOCK_MONOTONIC_RAW, tstamp);
80 return current_level(iodev);
81 }
82
delay_frames(const struct cras_iodev * iodev)83 static int delay_frames(const struct cras_iodev *iodev)
84 {
85 return 0;
86 }
87
close_dev(struct cras_iodev * iodev)88 static int close_dev(struct cras_iodev *iodev)
89 {
90 struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
91
92 empty_iodev->open = 0;
93 free(empty_iodev->audio_buffer);
94 empty_iodev->audio_buffer = NULL;
95 cras_iodev_free_audio_area(iodev);
96 return 0;
97 }
98
configure_dev(struct cras_iodev * iodev)99 static int configure_dev(struct cras_iodev *iodev)
100 {
101 struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
102
103 if (iodev->format == NULL)
104 return -EINVAL;
105
106 cras_iodev_init_audio_area(iodev, iodev->format->num_channels);
107 empty_iodev->open = 1;
108 empty_iodev->audio_buffer = calloc(1, EMPTY_BUFFER_SIZE);
109 empty_iodev->buffer_level = 0;
110
111 clock_gettime(CLOCK_MONOTONIC_RAW, &empty_iodev->last_buffer_access);
112
113 return 0;
114 }
115
get_buffer(struct cras_iodev * iodev,struct cras_audio_area ** area,unsigned * frames)116 static int get_buffer(struct cras_iodev *iodev,
117 struct cras_audio_area **area,
118 unsigned *frames)
119 {
120 struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
121 unsigned int avail, current;
122
123 if (iodev->direction == CRAS_STREAM_OUTPUT) {
124 avail = EMPTY_FRAMES - current_level(iodev);
125 *frames = MIN(*frames, avail);
126 } else {
127 current = current_level(iodev);
128 *frames = MIN(*frames, current);
129 }
130
131 iodev->area->frames = *frames;
132 cras_audio_area_config_buf_pointers(iodev->area, iodev->format,
133 empty_iodev->audio_buffer);
134 *area = iodev->area;
135 return 0;
136 }
137
put_buffer(struct cras_iodev * iodev,unsigned frames)138 static int put_buffer(struct cras_iodev *iodev, unsigned frames)
139 {
140 struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
141
142 empty_iodev->buffer_level = current_level(iodev);
143
144 clock_gettime(CLOCK_MONOTONIC_RAW, &empty_iodev->last_buffer_access);
145
146 if (iodev->direction == CRAS_STREAM_OUTPUT) {
147 empty_iodev->buffer_level += frames;
148 empty_iodev->buffer_level %= EMPTY_FRAMES;
149 } else {
150 /* Input */
151 if (empty_iodev->buffer_level > frames)
152 empty_iodev->buffer_level -= frames;
153 else
154 empty_iodev->buffer_level = 0;
155 }
156
157 return 0;
158 }
159
flush_buffer(struct cras_iodev * iodev)160 static int flush_buffer(struct cras_iodev *iodev)
161 {
162 struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
163
164 empty_iodev->buffer_level = current_level(iodev);
165 if (iodev->direction == CRAS_STREAM_INPUT) {
166 empty_iodev->buffer_level = 0;
167 clock_gettime(CLOCK_MONOTONIC_RAW,
168 &empty_iodev->last_buffer_access);
169 }
170 return 0;
171 }
172
update_active_node(struct cras_iodev * iodev,unsigned node_idx,unsigned dev_enabled)173 static void update_active_node(struct cras_iodev *iodev, unsigned node_idx,
174 unsigned dev_enabled)
175 {
176 }
177
178 /*
179 * Exported Interface.
180 */
181
empty_iodev_create(enum CRAS_STREAM_DIRECTION direction,enum CRAS_NODE_TYPE node_type)182 struct cras_iodev *empty_iodev_create(enum CRAS_STREAM_DIRECTION direction,
183 enum CRAS_NODE_TYPE node_type)
184 {
185 struct empty_iodev *empty_iodev;
186 struct cras_iodev *iodev;
187 struct cras_ionode *node;
188
189 if (direction != CRAS_STREAM_INPUT && direction != CRAS_STREAM_OUTPUT)
190 return NULL;
191
192 empty_iodev = calloc(1, sizeof(*empty_iodev));
193 if (empty_iodev == NULL)
194 return NULL;
195 iodev = &empty_iodev->base;
196 iodev->direction = direction;
197
198 iodev->supported_rates = empty_supported_rates;
199 iodev->supported_channel_counts = empty_supported_channel_counts;
200 iodev->supported_formats = empty_supported_formats;
201 iodev->buffer_size = EMPTY_FRAMES;
202
203 iodev->configure_dev = configure_dev;
204 iodev->close_dev = close_dev;
205 iodev->frames_queued = frames_queued;
206 iodev->delay_frames = delay_frames;
207 iodev->get_buffer = get_buffer;
208 iodev->put_buffer = put_buffer;
209 iodev->flush_buffer = flush_buffer;
210 iodev->update_active_node = update_active_node;
211 iodev->no_stream = cras_iodev_default_no_stream_playback;
212
213 /* Create a dummy ionode */
214 node = (struct cras_ionode *)calloc(1, sizeof(*node));
215 node->dev = iodev;
216 node->type = node_type;
217 node->volume = 100;
218 strcpy(node->name, "(default)");
219 cras_iodev_add_node(iodev, node);
220 cras_iodev_set_active_node(iodev, node);
221
222 /* Finally add it to the appropriate iodev list. */
223 if (direction == CRAS_STREAM_INPUT) {
224 if (node->type == CRAS_NODE_TYPE_HOTWORD) {
225 snprintf(iodev->info.name,
226 ARRAY_SIZE(iodev->info.name),
227 "Silent hotword device.");
228 iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] =
229 '\0';
230 iodev->info.idx = SILENT_HOTWORD_DEVICE;
231 } else {
232 snprintf(iodev->info.name,
233 ARRAY_SIZE(iodev->info.name),
234 "Silent record device.");
235 iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] =
236 '\0';
237 iodev->info.idx = SILENT_RECORD_DEVICE;
238 }
239 } else {
240 snprintf(iodev->info.name,
241 ARRAY_SIZE(iodev->info.name),
242 "Silent playback device.");
243 iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] = '\0';
244 iodev->info.idx = SILENT_PLAYBACK_DEVICE;
245 }
246
247 return iodev;
248 }
249
empty_iodev_destroy(struct cras_iodev * iodev)250 void empty_iodev_destroy(struct cras_iodev *iodev)
251 {
252 struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
253
254 if (iodev->direction == CRAS_STREAM_INPUT)
255 cras_iodev_list_rm_input(iodev);
256 else
257 cras_iodev_list_rm_output(iodev);
258 free(iodev->active_node);
259 cras_iodev_free_resources(iodev);
260 free(empty_iodev);
261 }
262