blob: d97dde50e634f0cb50132594b4b257fcc6fe3347 [file] [log] [blame]
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <algorithm>
#include <memory>
extern "C" {
#include "cras_iodev.h"
#include "cras_rstream.h"
#include "cras_shm.h"
#include "cras_types.h"
#include "dev_stream.h"
#include "utlist.h"
}
#include "dev_io_stubs.h"
ShmPtr create_shm(size_t cb_threshold) {
uint32_t frame_bytes = 4;
uint32_t used_size = cb_threshold * 2 * frame_bytes;
ShmPtr shm(reinterpret_cast<struct cras_audio_shm*>(
calloc(1, sizeof(struct cras_audio_shm))),
destroy_shm);
shm->header = reinterpret_cast<struct cras_audio_shm_header*>(
calloc(1, sizeof(struct cras_audio_shm_header)));
shm->header->config.used_size = used_size;
shm->header->config.frame_bytes = frame_bytes;
shm->config = shm->header->config;
uint32_t samples_size = cras_shm_calculate_samples_size(used_size);
shm->samples = reinterpret_cast<uint8_t*>(calloc(1, samples_size));
shm->samples_info.length = samples_size;
return shm;
}
void destroy_shm(struct cras_audio_shm* shm) {
free(shm->header);
free(shm->samples);
free(shm);
}
RstreamPtr create_rstream(cras_stream_id_t id,
CRAS_STREAM_DIRECTION direction,
size_t cb_threshold,
const cras_audio_format* format,
cras_audio_shm* shm) {
RstreamPtr rstream(
reinterpret_cast<cras_rstream*>(calloc(1, sizeof(cras_rstream))), free);
rstream->stream_id = id;
rstream->direction = direction;
rstream->fd = RSTREAM_FAKE_POLL_FD;
rstream->buffer_frames = cb_threshold * 2;
rstream->cb_threshold = cb_threshold;
rstream->shm = shm;
rstream->format = *format;
cras_frames_to_time(cb_threshold, rstream->format.frame_rate,
&rstream->sleep_interval_ts);
return rstream;
}
DevStreamPtr create_dev_stream(unsigned int dev_id, cras_rstream* rstream) {
DevStreamPtr dstream(
reinterpret_cast<dev_stream*>(calloc(1, sizeof(dev_stream))), free);
dstream->dev_id = dev_id;
dstream->stream = rstream;
dstream->dev_rate = rstream->format.frame_rate;
dstream->is_running = true;
return dstream;
}
StreamPtr create_stream(cras_stream_id_t id,
unsigned int dev_id,
CRAS_STREAM_DIRECTION direction,
size_t cb_threshold,
const cras_audio_format* format) {
ShmPtr shm = create_shm(cb_threshold);
RstreamPtr rstream =
create_rstream(1, CRAS_STREAM_INPUT, cb_threshold, format, shm.get());
DevStreamPtr dstream = create_dev_stream(1, rstream.get());
StreamPtr s(
new Stream(std::move(shm), std::move(rstream), std::move(dstream)));
return s;
}
void AddFakeDataToStream(Stream* stream, unsigned int frames) {
cras_shm_check_write_overrun(stream->rstream->shm);
cras_shm_buffer_written(stream->rstream->shm, frames);
}
int delay_frames_stub(const struct cras_iodev* iodev) {
return 0;
}
IonodePtr create_ionode(CRAS_NODE_TYPE type) {
IonodePtr ionode(
reinterpret_cast<cras_ionode*>(calloc(1, sizeof(cras_ionode))), free);
ionode->type = type;
return ionode;
}
int fake_flush_buffer(struct cras_iodev* iodev) {
return 0;
}
IodevPtr create_open_iodev(CRAS_STREAM_DIRECTION direction,
size_t cb_threshold,
cras_audio_format* format,
cras_ionode* active_node) {
IodevPtr iodev(reinterpret_cast<cras_iodev*>(calloc(1, sizeof(cras_iodev))),
free);
iodev->is_enabled = 1;
iodev->direction = direction;
iodev->format = format;
iodev->state = CRAS_IODEV_STATE_OPEN;
iodev->delay_frames = delay_frames_stub;
iodev->active_node = active_node;
iodev->buffer_size = cb_threshold * 2;
iodev->min_cb_level = UINT_MAX;
iodev->max_cb_level = 0;
iodev->largest_cb_level = 0;
iodev->flush_buffer = &fake_flush_buffer;
return iodev;
}
DevicePtr create_device(CRAS_STREAM_DIRECTION direction,
size_t cb_threshold,
cras_audio_format* format,
CRAS_NODE_TYPE active_node_type) {
IonodePtr node = create_ionode(active_node_type);
IodevPtr dev = create_open_iodev(direction, cb_threshold, format, node.get());
OpendevPtr odev(reinterpret_cast<open_dev*>(calloc(1, sizeof(open_dev))),
free);
odev->dev = dev.get();
DevicePtr d(new Device(std::move(dev), std::move(node), std::move(odev)));
return d;
}
void add_stream_to_dev(IodevPtr& dev, const StreamPtr& stream) {
DL_APPEND(dev->streams, stream->dstream.get());
dev->min_cb_level = std::min(stream->rstream->cb_threshold,
static_cast<size_t>(dev->min_cb_level));
dev->max_cb_level = std::max(stream->rstream->cb_threshold,
static_cast<size_t>(dev->max_cb_level));
dev->largest_cb_level = std::max(stream->rstream->cb_threshold,
static_cast<size_t>(dev->max_cb_level));
if (stream->rstream->main_dev.dev_id == NO_DEVICE) {
stream->rstream->main_dev.dev_id = dev->info.idx;
stream->rstream->main_dev.dev_ptr = dev.get();
}
}
void fill_audio_format(cras_audio_format* format, unsigned int rate) {
format->format = SND_PCM_FORMAT_S16_LE;
format->frame_rate = rate;
format->num_channels = 2;
format->channel_layout[0] = 0;
format->channel_layout[1] = 1;
for (int i = 2; i < CRAS_CH_MAX; i++)
format->channel_layout[i] = -1;
}