Home | History | Annotate | Download | only in server
      1 /* Copyright (c) 2012 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 
      6 #include <pthread.h>
      7 #include <sys/param.h>
      8 #include <syslog.h>
      9 
     10 #include "cras_audio_area.h"
     11 #include "cras_config.h"
     12 #include "cras_iodev.h"
     13 #include "cras_iodev_list.h"
     14 #include "cras_rstream.h"
     15 #include "cras_types.h"
     16 #include "utlist.h"
     17 
     18 #define EMPTY_BUFFER_SIZE (16 * 1024)
     19 #define EMPTY_FRAME_SIZE 4
     20 #define EMPTY_FRAMES (EMPTY_BUFFER_SIZE / EMPTY_FRAME_SIZE)
     21 
     22 static size_t empty_supported_rates[] = {
     23 	44100, 48000, 0
     24 };
     25 
     26 static size_t empty_supported_channel_counts[] = {
     27 	1, 2, 0
     28 };
     29 
     30 static snd_pcm_format_t empty_supported_formats[] = {
     31 	SND_PCM_FORMAT_S16_LE,
     32 	SND_PCM_FORMAT_S24_LE,
     33 	SND_PCM_FORMAT_S32_LE,
     34 	SND_PCM_FORMAT_S24_3LE,
     35 	0
     36 };
     37 
     38 struct empty_iodev {
     39 	struct cras_iodev base;
     40 	int open;
     41 	uint8_t *audio_buffer;
     42 	unsigned int buffer_level;
     43 	struct timespec last_buffer_access;
     44 };
     45 
     46 /* Current level of the audio buffer.  This is made up based on what has been
     47  * read/written and how long it has been since then.  Simulates audio hardware
     48  * running at the given sample rate.
     49  */
     50 static unsigned int current_level(const struct cras_iodev *iodev)
     51 {
     52 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
     53 	unsigned int frames, frames_since_last;
     54 
     55 	frames = empty_iodev->buffer_level;
     56 	frames_since_last = cras_frames_since_time(
     57 			&empty_iodev->last_buffer_access,
     58 			iodev->format->frame_rate);
     59 
     60 	if (iodev->direction == CRAS_STREAM_INPUT)
     61 		return (frames + frames_since_last) % EMPTY_FRAMES;
     62 
     63 	/* output */
     64 	if (frames <= frames_since_last)
     65 		return 0;
     66 	return frames - frames_since_last;
     67 }
     68 
     69 /*
     70  * iodev callbacks.
     71  */
     72 
     73 static int frames_queued(const struct cras_iodev *iodev,
     74 			 struct timespec *tstamp)
     75 {
     76 	clock_gettime(CLOCK_MONOTONIC_RAW, tstamp);
     77 	return current_level(iodev);
     78 }
     79 
     80 static int delay_frames(const struct cras_iodev *iodev)
     81 {
     82 	return 0;
     83 }
     84 
     85 static int close_dev(struct cras_iodev *iodev)
     86 {
     87 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
     88 
     89 	empty_iodev->open = 0;
     90 	free(empty_iodev->audio_buffer);
     91 	empty_iodev->audio_buffer = NULL;
     92 	cras_iodev_free_audio_area(iodev);
     93 	return 0;
     94 }
     95 
     96 static int open_dev(struct cras_iodev *iodev)
     97 {
     98 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
     99 
    100 	if (iodev->format == NULL)
    101 		return -EINVAL;
    102 
    103 	cras_iodev_init_audio_area(iodev, iodev->format->num_channels);
    104 	empty_iodev->open = 1;
    105 	empty_iodev->audio_buffer = calloc(1, EMPTY_BUFFER_SIZE);
    106 	empty_iodev->buffer_level = 0;
    107 
    108 	clock_gettime(CLOCK_MONOTONIC_RAW, &empty_iodev->last_buffer_access);
    109 
    110 	return 0;
    111 }
    112 
    113 static int get_buffer(struct cras_iodev *iodev,
    114 		      struct cras_audio_area **area,
    115 		      unsigned *frames)
    116 {
    117 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
    118 	unsigned int avail, current;
    119 
    120 	if (iodev->direction == CRAS_STREAM_OUTPUT) {
    121 		avail = EMPTY_FRAMES - current_level(iodev);
    122 		*frames = MIN(*frames, avail);
    123 	} else {
    124 		current = current_level(iodev);
    125 		*frames = MIN(*frames, current);
    126 	}
    127 
    128 	iodev->area->frames = *frames;
    129 	cras_audio_area_config_buf_pointers(iodev->area, iodev->format,
    130 			empty_iodev->audio_buffer);
    131 	*area = iodev->area;
    132 	return 0;
    133 }
    134 
    135 static int put_buffer(struct cras_iodev *iodev, unsigned frames)
    136 {
    137 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
    138 
    139 	empty_iodev->buffer_level = current_level(iodev);
    140 
    141 	clock_gettime(CLOCK_MONOTONIC_RAW, &empty_iodev->last_buffer_access);
    142 
    143 	if (iodev->direction == CRAS_STREAM_OUTPUT) {
    144 		empty_iodev->buffer_level += frames;
    145 		empty_iodev->buffer_level %= EMPTY_FRAMES;
    146 	} else {
    147 		/* Input */
    148 		if (empty_iodev->buffer_level > frames)
    149 			empty_iodev->buffer_level -= frames;
    150 		else
    151 			empty_iodev->buffer_level = 0;
    152 	}
    153 
    154 	return 0;
    155 }
    156 
    157 static int flush_buffer(struct cras_iodev *iodev)
    158 {
    159 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
    160 
    161 	empty_iodev->buffer_level = current_level(iodev);
    162 	if (iodev->direction == CRAS_STREAM_INPUT) {
    163 		empty_iodev->buffer_level = 0;
    164 		clock_gettime(CLOCK_MONOTONIC_RAW,
    165 			      &empty_iodev->last_buffer_access);
    166 	}
    167 	return 0;
    168 }
    169 
    170 static void update_active_node(struct cras_iodev *iodev, unsigned node_idx,
    171 			       unsigned dev_enabled)
    172 {
    173 }
    174 
    175 /*
    176  * Exported Interface.
    177  */
    178 
    179 struct cras_iodev *empty_iodev_create(enum CRAS_STREAM_DIRECTION direction)
    180 {
    181 	struct empty_iodev *empty_iodev;
    182 	struct cras_iodev *iodev;
    183 	struct cras_ionode *node;
    184 
    185 	if (direction != CRAS_STREAM_INPUT && direction != CRAS_STREAM_OUTPUT)
    186 		return NULL;
    187 
    188 	empty_iodev = calloc(1, sizeof(*empty_iodev));
    189 	if (empty_iodev == NULL)
    190 		return NULL;
    191 	iodev = &empty_iodev->base;
    192 	iodev->direction = direction;
    193 
    194 	iodev->supported_rates = empty_supported_rates;
    195 	iodev->supported_channel_counts = empty_supported_channel_counts;
    196 	iodev->supported_formats = empty_supported_formats;
    197 	iodev->buffer_size = EMPTY_FRAMES;
    198 
    199 	iodev->open_dev = open_dev;
    200 	iodev->close_dev = close_dev;
    201 	iodev->frames_queued = frames_queued;
    202 	iodev->delay_frames = delay_frames;
    203 	iodev->get_buffer = get_buffer;
    204 	iodev->put_buffer = put_buffer;
    205 	iodev->flush_buffer = flush_buffer;
    206 	iodev->update_active_node = update_active_node;
    207 	iodev->no_stream = cras_iodev_default_no_stream_playback;
    208 
    209 	/* Create a dummy ionode */
    210 	node = (struct cras_ionode *)calloc(1, sizeof(*node));
    211 	node->dev = iodev;
    212 	node->type = CRAS_NODE_TYPE_UNKNOWN;
    213 	node->volume = 100;
    214 	strcpy(node->name, "(default)");
    215 	cras_iodev_add_node(iodev, node);
    216 	cras_iodev_set_active_node(iodev, node);
    217 
    218 	/* Finally add it to the appropriate iodev list. */
    219 	if (direction == CRAS_STREAM_INPUT) {
    220 		snprintf(iodev->info.name,
    221 			 ARRAY_SIZE(iodev->info.name),
    222 			 "Silent record device.");
    223 		iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] = '\0';
    224 		iodev->info.idx = SILENT_RECORD_DEVICE;
    225 	} else {
    226 		snprintf(iodev->info.name,
    227 			 ARRAY_SIZE(iodev->info.name),
    228 			 "Silent playback device.");
    229 		iodev->info.name[ARRAY_SIZE(iodev->info.name) - 1] = '\0';
    230 		iodev->info.idx = SILENT_PLAYBACK_DEVICE;
    231 	}
    232 
    233 	return iodev;
    234 }
    235 
    236 void empty_iodev_destroy(struct cras_iodev *iodev)
    237 {
    238 	struct empty_iodev *empty_iodev = (struct empty_iodev *)iodev;
    239 
    240 	if (iodev->direction == CRAS_STREAM_INPUT)
    241 		cras_iodev_list_rm_input(iodev);
    242 	else
    243 		cras_iodev_list_rm_output(iodev);
    244 	free(iodev->active_node);
    245 	cras_iodev_free_resources(iodev);
    246 	free(empty_iodev);
    247 }
    248