summaryrefslogtreecommitdiff
path: root/cras/src/server/cras_loopback_iodev.c
diff options
context:
space:
mode:
Diffstat (limited to 'cras/src/server/cras_loopback_iodev.c')
-rw-r--r--cras/src/server/cras_loopback_iodev.c362
1 files changed, 0 insertions, 362 deletions
diff --git a/cras/src/server/cras_loopback_iodev.c b/cras/src/server/cras_loopback_iodev.c
deleted file mode 100644
index cf3ba4ae..00000000
--- a/cras/src/server/cras_loopback_iodev.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/* Copyright (c) 2013 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 <pthread.h>
-#include <sys/param.h>
-#include <syslog.h>
-
-#include "audio_thread_log.h"
-#include "byte_buffer.h"
-#include "cras_audio_area.h"
-#include "cras_config.h"
-#include "cras_iodev.h"
-#include "cras_iodev_list.h"
-#include "cras_types.h"
-#include "cras_util.h"
-#include "sfh.h"
-#include "utlist.h"
-
-#define LOOPBACK_BUFFER_SIZE 8192
-
-static const char *loopdev_names[LOOPBACK_NUM_TYPES] = {
- "Post Mix Pre DSP Loopback",
- "Post DSP Loopback",
-};
-
-static size_t loopback_supported_rates[] = { 48000, 0 };
-
-static size_t loopback_supported_channel_counts[] = { 2, 0 };
-
-static snd_pcm_format_t loopback_supported_formats[] = {
- SND_PCM_FORMAT_S16_LE,
- 0,
-};
-
-/* loopack iodev. Keep state of a loopback device.
- * loopback_type - Pre-dsp or post-dsp.
- * read_frames - Frames of audio data read since last dev start.
- * started - True to indicate the target device is running, otherwise false.
- * dev_start_time - The timestamp of the last call to configure_dev.
- * sample_buffer - Pointer to sample buffer.
- * sender_idx - Index of the output device to read loopback audio.
- */
-struct loopback_iodev {
- struct cras_iodev base;
- enum CRAS_LOOPBACK_TYPE loopback_type;
- uint64_t read_frames;
- bool started;
- struct timespec dev_start_time;
- struct byte_buffer *sample_buffer;
- unsigned int sender_idx;
-};
-
-static int sample_hook_start(bool start, void *cb_data)
-{
- struct loopback_iodev *loopdev = (struct loopback_iodev *)cb_data;
- loopdev->started = start;
- return 0;
-}
-
-/*
- * Called in the put buffer function of the sender that hooked to.
- *
- * Returns:
- * Number of frames copied to the sample buffer in the hook.
- */
-static int sample_hook(const uint8_t *frames, unsigned int nframes,
- const struct cras_audio_format *fmt, void *cb_data)
-{
- struct loopback_iodev *loopdev = (struct loopback_iodev *)cb_data;
- struct byte_buffer *sbuf = loopdev->sample_buffer;
- unsigned int frame_bytes = cras_get_format_bytes(fmt);
- unsigned int frames_to_copy, bytes_to_copy, frames_copied = 0;
- int i;
-
- for (i = 0; i < 2; i++) {
- frames_to_copy = MIN(buf_writable(sbuf) / frame_bytes, nframes);
- if (!frames_to_copy)
- break;
-
- bytes_to_copy = frames_to_copy * frame_bytes;
- memcpy(buf_write_pointer(sbuf), frames, bytes_to_copy);
- buf_increment_write(sbuf, bytes_to_copy);
- frames += bytes_to_copy;
- nframes -= frames_to_copy;
- frames_copied += frames_to_copy;
- }
-
- ATLOG(atlog, AUDIO_THREAD_LOOPBACK_SAMPLE_HOOK, nframes + frames_copied,
- frames_copied, 0);
-
- return frames_copied;
-}
-
-static void update_first_output_to_loopback(struct loopback_iodev *loopdev)
-{
- struct cras_iodev *edev;
-
- /* Register loopback hook onto first enabled iodev. */
- edev = cras_iodev_list_get_first_enabled_iodev(CRAS_STREAM_OUTPUT);
- if (edev) {
- loopdev->sender_idx = edev->info.idx;
- cras_iodev_list_register_loopback(
- loopdev->loopback_type, loopdev->sender_idx,
- sample_hook, sample_hook_start, loopdev->base.info.idx);
- }
-}
-
-static void device_enabled_hook(struct cras_iodev *iodev, void *cb_data)
-{
- struct loopback_iodev *loopdev = (struct loopback_iodev *)cb_data;
-
- if (iodev->direction != CRAS_STREAM_OUTPUT)
- return;
-
- update_first_output_to_loopback(loopdev);
-}
-
-static void device_disabled_hook(struct cras_iodev *iodev, void *cb_data)
-{
- struct loopback_iodev *loopdev = (struct loopback_iodev *)cb_data;
-
- if (loopdev->sender_idx != iodev->info.idx)
- return;
-
- /* Unregister loopback hook from disabled iodev. */
- cras_iodev_list_unregister_loopback(loopdev->loopback_type,
- loopdev->sender_idx,
- loopdev->base.info.idx);
- update_first_output_to_loopback(loopdev);
-}
-
-/*
- * iodev callbacks.
- */
-
-static int frames_queued(const struct cras_iodev *iodev,
- struct timespec *hw_tstamp)
-{
- struct loopback_iodev *loopdev = (struct loopback_iodev *)iodev;
- struct byte_buffer *sbuf = loopdev->sample_buffer;
- unsigned int frame_bytes = cras_get_format_bytes(iodev->format);
-
- if (!loopdev->started) {
- unsigned int frames_since_start, frames_to_fill, bytes_to_fill;
-
- frames_since_start = cras_frames_since_time(
- &loopdev->dev_start_time, iodev->format->frame_rate);
- frames_to_fill =
- frames_since_start > loopdev->read_frames ?
- frames_since_start - loopdev->read_frames :
- 0;
- frames_to_fill =
- MIN(buf_writable(sbuf) / frame_bytes, frames_to_fill);
- if (frames_to_fill > 0) {
- bytes_to_fill = frames_to_fill * frame_bytes;
- memset(buf_write_pointer(sbuf), 0, bytes_to_fill);
- buf_increment_write(sbuf, bytes_to_fill);
- }
- }
- clock_gettime(CLOCK_MONOTONIC_RAW, hw_tstamp);
- return buf_queued(sbuf) / frame_bytes;
-}
-
-static int delay_frames(const struct cras_iodev *iodev)
-{
- struct timespec tstamp;
-
- return frames_queued(iodev, &tstamp);
-}
-
-static int close_record_dev(struct cras_iodev *iodev)
-{
- struct loopback_iodev *loopdev = (struct loopback_iodev *)iodev;
- struct byte_buffer *sbuf = loopdev->sample_buffer;
-
- cras_iodev_free_format(iodev);
- cras_iodev_free_audio_area(iodev);
- buf_reset(sbuf);
-
- cras_iodev_list_unregister_loopback(loopdev->loopback_type,
- loopdev->sender_idx,
- loopdev->base.info.idx);
- loopdev->sender_idx = NO_DEVICE;
- cras_iodev_list_set_device_enabled_callback(NULL, NULL, (void *)iodev);
-
- return 0;
-}
-
-static int configure_record_dev(struct cras_iodev *iodev)
-{
- struct loopback_iodev *loopdev = (struct loopback_iodev *)iodev;
- struct cras_iodev *edev;
-
- cras_iodev_init_audio_area(iodev, iodev->format->num_channels);
- clock_gettime(CLOCK_MONOTONIC_RAW, &loopdev->dev_start_time);
- loopdev->read_frames = 0;
- loopdev->started = 0;
-
- edev = cras_iodev_list_get_first_enabled_iodev(CRAS_STREAM_OUTPUT);
- if (edev) {
- loopdev->sender_idx = edev->info.idx;
- cras_iodev_list_register_loopback(
- loopdev->loopback_type, loopdev->sender_idx,
- sample_hook, sample_hook_start, iodev->info.idx);
- }
- cras_iodev_list_set_device_enabled_callback(
- device_enabled_hook, device_disabled_hook, (void *)iodev);
-
- return 0;
-}
-
-static int get_record_buffer(struct cras_iodev *iodev,
- struct cras_audio_area **area, unsigned *frames)
-{
- struct loopback_iodev *loopdev = (struct loopback_iodev *)iodev;
- struct byte_buffer *sbuf = loopdev->sample_buffer;
- unsigned int frame_bytes = cras_get_format_bytes(iodev->format);
- unsigned int avail_frames = buf_readable(sbuf) / frame_bytes;
-
- ATLOG(atlog, AUDIO_THREAD_LOOPBACK_GET, *frames, avail_frames, 0);
-
- *frames = MIN(avail_frames, *frames);
- iodev->area->frames = *frames;
- cras_audio_area_config_buf_pointers(iodev->area, iodev->format,
- buf_read_pointer(sbuf));
- *area = iodev->area;
-
- return 0;
-}
-
-static int put_record_buffer(struct cras_iodev *iodev, unsigned nframes)
-{
- struct loopback_iodev *loopdev = (struct loopback_iodev *)iodev;
- struct byte_buffer *sbuf = loopdev->sample_buffer;
- unsigned int frame_bytes = cras_get_format_bytes(iodev->format);
-
- buf_increment_read(sbuf, (size_t)nframes * (size_t)frame_bytes);
- loopdev->read_frames += nframes;
- ATLOG(atlog, AUDIO_THREAD_LOOPBACK_PUT, nframes, 0, 0);
- return 0;
-}
-
-static int flush_record_buffer(struct cras_iodev *iodev)
-{
- struct loopback_iodev *loopdev = (struct loopback_iodev *)iodev;
- struct byte_buffer *sbuf = loopdev->sample_buffer;
- unsigned int queued_bytes = buf_queued(sbuf);
- buf_increment_read(sbuf, queued_bytes);
- loopdev->read_frames = 0;
- return 0;
-}
-
-static void update_active_node(struct cras_iodev *iodev, unsigned node_idx,
- unsigned dev_enabled)
-{
-}
-
-static struct cras_iodev *create_loopback_iodev(enum CRAS_LOOPBACK_TYPE type)
-{
- struct loopback_iodev *loopback_iodev;
- struct cras_iodev *iodev;
-
- loopback_iodev = calloc(1, sizeof(*loopback_iodev));
- if (loopback_iodev == NULL)
- return NULL;
-
- loopback_iodev->sample_buffer = byte_buffer_create(1024 * 16 * 4);
- if (loopback_iodev->sample_buffer == NULL) {
- free(loopback_iodev);
- return NULL;
- }
-
- loopback_iodev->loopback_type = type;
-
- iodev = &loopback_iodev->base;
- iodev->direction = CRAS_STREAM_INPUT;
- snprintf(iodev->info.name, ARRAY_SIZE(iodev->info.name), "%s",
- loopdev_names[type]);
- iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] = '\0';
- iodev->info.stable_id =
- SuperFastHash(iodev->info.name, strlen(iodev->info.name),
- strlen(iodev->info.name));
-
- iodev->supported_rates = loopback_supported_rates;
- iodev->supported_channel_counts = loopback_supported_channel_counts;
- iodev->supported_formats = loopback_supported_formats;
- iodev->buffer_size = LOOPBACK_BUFFER_SIZE;
-
- iodev->frames_queued = frames_queued;
- iodev->delay_frames = delay_frames;
- iodev->update_active_node = update_active_node;
- iodev->configure_dev = configure_record_dev;
- iodev->close_dev = close_record_dev;
- iodev->get_buffer = get_record_buffer;
- iodev->put_buffer = put_record_buffer;
- iodev->flush_buffer = flush_record_buffer;
-
- /*
- * Record max supported channels into cras_iodev_info.
- * The value is the max of loopback_supported_channel_counts.
- */
- iodev->info.max_supported_channels = 2;
-
- return iodev;
-}
-
-/*
- * Exported Interface.
- */
-
-struct cras_iodev *loopback_iodev_create(enum CRAS_LOOPBACK_TYPE type)
-{
- struct cras_iodev *iodev;
- struct cras_ionode *node;
- enum CRAS_NODE_TYPE node_type;
-
- switch (type) {
- case LOOPBACK_POST_MIX_PRE_DSP:
- node_type = CRAS_NODE_TYPE_POST_MIX_PRE_DSP;
- break;
- case LOOPBACK_POST_DSP:
- node_type = CRAS_NODE_TYPE_POST_DSP;
- break;
- default:
- return NULL;
- }
-
- iodev = create_loopback_iodev(type);
- if (iodev == NULL)
- return NULL;
-
- /* Create an empty ionode */
- node = (struct cras_ionode *)calloc(1, sizeof(*node));
- node->dev = iodev;
- node->type = node_type;
- node->plugged = 1;
- node->volume = 100;
- node->ui_gain_scaler = 1.0f;
- node->stable_id = iodev->info.stable_id;
- node->software_volume_needed = 0;
- strcpy(node->name, loopdev_names[type]);
- cras_iodev_add_node(iodev, node);
- cras_iodev_set_active_node(iodev, node);
-
- cras_iodev_list_add_input(iodev);
-
- return iodev;
-}
-
-void loopback_iodev_destroy(struct cras_iodev *iodev)
-{
- struct loopback_iodev *loopdev = (struct loopback_iodev *)iodev;
- struct byte_buffer *sbuf = loopdev->sample_buffer;
-
- cras_iodev_list_rm_input(iodev);
- free(iodev->nodes);
-
- byte_buffer_destroy(&sbuf);
- free(loopdev);
-}