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