1 // Copyright 2017 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 #include <stdint.h>
6 #include <stdio.h>
7 #include <time.h>
8
9 #include <algorithm>
10 #include <memory>
11
12 extern "C" {
13 #include "cras_iodev.h"
14 #include "cras_rstream.h"
15 #include "cras_shm.h"
16 #include "cras_types.h"
17 #include "dev_stream.h"
18 #include "utlist.h"
19 }
20
21 #include "dev_io_stubs.h"
22
create_shm(size_t cb_threshold)23 ShmPtr create_shm(size_t cb_threshold) {
24 uint32_t frame_bytes = 4;
25 uint32_t used_size = cb_threshold * 2 * frame_bytes;
26
27 ShmPtr shm(reinterpret_cast<struct cras_audio_shm*>(
28 calloc(1, sizeof(struct cras_audio_shm))),
29 destroy_shm);
30
31 shm->header = reinterpret_cast<struct cras_audio_shm_header*>(
32 calloc(1, sizeof(struct cras_audio_shm_header)));
33 shm->header->config.used_size = used_size;
34 shm->header->config.frame_bytes = frame_bytes;
35 shm->config = shm->header->config;
36
37 uint32_t samples_size = cras_shm_calculate_samples_size(used_size);
38 shm->samples = reinterpret_cast<uint8_t*>(calloc(1, samples_size));
39 shm->samples_info.length = samples_size;
40 return shm;
41 }
42
destroy_shm(struct cras_audio_shm * shm)43 void destroy_shm(struct cras_audio_shm* shm) {
44 free(shm->header);
45 free(shm->samples);
46 free(shm);
47 }
48
create_rstream(cras_stream_id_t id,CRAS_STREAM_DIRECTION direction,size_t cb_threshold,const cras_audio_format * format,cras_audio_shm * shm)49 RstreamPtr create_rstream(cras_stream_id_t id,
50 CRAS_STREAM_DIRECTION direction,
51 size_t cb_threshold,
52 const cras_audio_format* format,
53 cras_audio_shm* shm) {
54 RstreamPtr rstream(
55 reinterpret_cast<cras_rstream*>(calloc(1, sizeof(cras_rstream))), free);
56 rstream->stream_id = id;
57 rstream->direction = direction;
58 rstream->fd = RSTREAM_FAKE_POLL_FD;
59 rstream->buffer_frames = cb_threshold * 2;
60 rstream->cb_threshold = cb_threshold;
61 rstream->shm = shm;
62 rstream->format = *format;
63 cras_frames_to_time(cb_threshold, rstream->format.frame_rate,
64 &rstream->sleep_interval_ts);
65 return rstream;
66 }
67
create_dev_stream(unsigned int dev_id,cras_rstream * rstream)68 DevStreamPtr create_dev_stream(unsigned int dev_id, cras_rstream* rstream) {
69 DevStreamPtr dstream(
70 reinterpret_cast<dev_stream*>(calloc(1, sizeof(dev_stream))), free);
71 dstream->dev_id = dev_id;
72 dstream->stream = rstream;
73 dstream->dev_rate = rstream->format.frame_rate;
74 dstream->is_running = true;
75 return dstream;
76 }
77
create_stream(cras_stream_id_t id,unsigned int dev_id,CRAS_STREAM_DIRECTION direction,size_t cb_threshold,const cras_audio_format * format)78 StreamPtr create_stream(cras_stream_id_t id,
79 unsigned int dev_id,
80 CRAS_STREAM_DIRECTION direction,
81 size_t cb_threshold,
82 const cras_audio_format* format) {
83 ShmPtr shm = create_shm(cb_threshold);
84 RstreamPtr rstream =
85 create_rstream(1, CRAS_STREAM_INPUT, cb_threshold, format, shm.get());
86 DevStreamPtr dstream = create_dev_stream(1, rstream.get());
87 StreamPtr s(
88 new Stream(std::move(shm), std::move(rstream), std::move(dstream)));
89 return s;
90 }
91
AddFakeDataToStream(Stream * stream,unsigned int frames)92 void AddFakeDataToStream(Stream* stream, unsigned int frames) {
93 cras_shm_check_write_overrun(stream->rstream->shm);
94 cras_shm_buffer_written(stream->rstream->shm, frames);
95 }
96
delay_frames_stub(const struct cras_iodev * iodev)97 int delay_frames_stub(const struct cras_iodev* iodev) {
98 return 0;
99 }
100
create_ionode(CRAS_NODE_TYPE type)101 IonodePtr create_ionode(CRAS_NODE_TYPE type) {
102 IonodePtr ionode(
103 reinterpret_cast<cras_ionode*>(calloc(1, sizeof(cras_ionode))), free);
104 ionode->type = type;
105 return ionode;
106 }
107
fake_flush_buffer(struct cras_iodev * iodev)108 int fake_flush_buffer(struct cras_iodev* iodev) {
109 return 0;
110 }
111
create_open_iodev(CRAS_STREAM_DIRECTION direction,size_t cb_threshold,cras_audio_format * format,cras_ionode * active_node)112 IodevPtr create_open_iodev(CRAS_STREAM_DIRECTION direction,
113 size_t cb_threshold,
114 cras_audio_format* format,
115 cras_ionode* active_node) {
116 IodevPtr iodev(reinterpret_cast<cras_iodev*>(calloc(1, sizeof(cras_iodev))),
117 free);
118 iodev->is_enabled = 1;
119 iodev->direction = direction;
120 iodev->format = format;
121 iodev->state = CRAS_IODEV_STATE_OPEN;
122 iodev->delay_frames = delay_frames_stub;
123 iodev->active_node = active_node;
124 iodev->buffer_size = cb_threshold * 2;
125 iodev->min_cb_level = UINT_MAX;
126 iodev->max_cb_level = 0;
127 iodev->largest_cb_level = 0;
128 iodev->flush_buffer = &fake_flush_buffer;
129 return iodev;
130 }
131
create_device(CRAS_STREAM_DIRECTION direction,size_t cb_threshold,cras_audio_format * format,CRAS_NODE_TYPE active_node_type)132 DevicePtr create_device(CRAS_STREAM_DIRECTION direction,
133 size_t cb_threshold,
134 cras_audio_format* format,
135 CRAS_NODE_TYPE active_node_type) {
136 IonodePtr node = create_ionode(active_node_type);
137 IodevPtr dev = create_open_iodev(direction, cb_threshold, format, node.get());
138 OpendevPtr odev(reinterpret_cast<open_dev*>(calloc(1, sizeof(open_dev))),
139 free);
140 odev->dev = dev.get();
141
142 DevicePtr d(new Device(std::move(dev), std::move(node), std::move(odev)));
143 return d;
144 }
145
add_stream_to_dev(IodevPtr & dev,const StreamPtr & stream)146 void add_stream_to_dev(IodevPtr& dev, const StreamPtr& stream) {
147 DL_APPEND(dev->streams, stream->dstream.get());
148 dev->min_cb_level = std::min(stream->rstream->cb_threshold,
149 static_cast<size_t>(dev->min_cb_level));
150 dev->max_cb_level = std::max(stream->rstream->cb_threshold,
151 static_cast<size_t>(dev->max_cb_level));
152 dev->largest_cb_level = std::max(stream->rstream->cb_threshold,
153 static_cast<size_t>(dev->max_cb_level));
154
155 if (stream->rstream->main_dev.dev_id == NO_DEVICE) {
156 stream->rstream->main_dev.dev_id = dev->info.idx;
157 stream->rstream->main_dev.dev_ptr = dev.get();
158 }
159 }
160
fill_audio_format(cras_audio_format * format,unsigned int rate)161 void fill_audio_format(cras_audio_format* format, unsigned int rate) {
162 format->format = SND_PCM_FORMAT_S16_LE;
163 format->frame_rate = rate;
164 format->num_channels = 2;
165 format->channel_layout[0] = 0;
166 format->channel_layout[1] = 1;
167 for (int i = 2; i < CRAS_CH_MAX; i++)
168 format->channel_layout[i] = -1;
169 }
170