• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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