1 /* Copyright 2018 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 <syslog.h>
7 
8 #include "cras_rstream.h"
9 #include "cras_server.h"
10 #include "cras_system_state.h"
11 #include "cras_types.h"
12 #include "server_stream.h"
13 #include "stream_list.h"
14 
15 
16 /* Parameters used for server stream. */
17 static unsigned int server_stream_block_size = 480;
18 
19 /*
20  * Server stream doesn't care what format is used, because no
21  * client is reading data from stream. The main point is to
22  * make pinned device open and let data flow through its dsp
23  * pipeline.
24  */
25 static struct cras_audio_format format =
26 {
27 	SND_PCM_FORMAT_S16_LE,
28 	48000,
29 	2,
30 };
31 
32 /*
33  * Information of a stream created by server. Currently only
34  * one server stream is allowed, for echo reference use.
35  */
36 static struct cras_rstream_config *stream_config;
37 
38 /* Actually create the server stream and add to stream list. */
server_stream_add_cb(void * data)39 static void server_stream_add_cb(void *data)
40 {
41 	struct stream_list *stream_list = (struct stream_list *)data;
42 	struct cras_rstream *stream;
43 
44 	if (!stream_config)
45 		return;
46 
47 	stream_list_add(stream_list, stream_config, &stream);
48 }
49 
server_stream_create(struct stream_list * stream_list,unsigned int dev_idx)50 void server_stream_create(struct stream_list *stream_list, unsigned int dev_idx)
51 {
52 	if (stream_config) {
53 		syslog(LOG_ERR, "server stream already exists, dev %u",
54 		       stream_config->dev_idx);
55 		return;
56 	}
57 
58 	stream_config = (struct cras_rstream_config *)
59 			calloc(1, sizeof(*stream_config));
60 	stream_config->format = &format;
61 	stream_config->stream_id =
62 			cras_get_stream_id(SERVER_STREAM_CLIENT_ID, 0);
63 	stream_config->stream_type = CRAS_STREAM_TYPE_DEFAULT;
64 	stream_config->direction = CRAS_STREAM_INPUT;
65 	stream_config->flags = SERVER_ONLY;
66 	stream_config->buffer_frames = server_stream_block_size;
67 	stream_config->cb_threshold = server_stream_block_size;
68 	stream_config->dev_idx = dev_idx;
69 	stream_config->audio_fd = -1;
70 
71 	/* Schedule add stream in next main thread loop. */
72 	cras_system_add_task(server_stream_add_cb, stream_list);
73 }
74 
server_stream_rm_cb(void * data)75 static void server_stream_rm_cb(void *data)
76 {
77 	struct stream_list *stream_list = (struct stream_list *)data;
78 
79 	if (stream_config == NULL)
80 		return;
81 
82 	if (stream_list_rm(stream_list, stream_config->stream_id))
83 		syslog(LOG_ERR, "Server stream %x no longer exist",
84 		       stream_config->stream_id);
85 
86 	free(stream_config);
87 	stream_config = NULL;
88 }
89 
server_stream_destroy(struct stream_list * stream_list,unsigned int dev_idx)90 void server_stream_destroy(struct stream_list *stream_list,
91 			   unsigned int dev_idx)
92 {
93 	if (!stream_config || stream_config->dev_idx != dev_idx) {
94 		syslog(LOG_ERR, "No server stream to destroy");
95 		return;
96 	}
97 	/* Schedule remove stream in next main thread loop. */
98 	cras_system_add_task(server_stream_rm_cb, stream_list);
99 }
100