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