cras_helpers.c revision a6de2464f12ba758ee978ebe6b104c59757464a8
11d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid/* Copyright (c) 2015 The Chromium OS Authors. All rights reserved.
21d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid * Use of this source code is governed by a BSD-style license that can be
31d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid * found in the LICENSE file.
41d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid */
51d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
61d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid#include <stdint.h>
71d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid#include <sys/param.h>
81d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
91d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid#include "cras_client.h"
101d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid#include "cras_util.h"
111d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
121d21d2f9bb82889781b4be087ad65ba488608866Dylan Reidstruct buffer_data {
13a6de2464f12ba758ee978ebe6b104c59757464a8Nathan Bullock	const uint8_t *buffer;
141d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	unsigned int offset;
151d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	unsigned int frame_bytes;
161d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	unsigned int len;
171d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid};
181d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
191d21d2f9bb82889781b4be087ad65ba488608866Dylan Reidstatic int play_buffer_callback(struct cras_client *client,
201d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				cras_stream_id_t stream_id,
211d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				uint8_t *captured_samples,
221d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				uint8_t *playback_samples,
231d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				unsigned int frames,
241d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				const struct timespec *captured_time,
251d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				const struct timespec *playback_time,
261d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				void *user_arg)
271d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid{
281d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	struct buffer_data *data = (struct buffer_data *)user_arg;
291d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	int to_copy = data->len - data->offset;
301d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
311d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	if (to_copy <= 0) {
321d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid		free(user_arg);
331d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid		return EOF;
341d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	}
351d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
361d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	to_copy = MIN(to_copy, frames * data->frame_bytes);
371d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
381d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	memcpy(playback_samples, data->buffer + data->offset, to_copy);
391d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
401d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	data->offset += to_copy;
411d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
421d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	return to_copy / data->frame_bytes;
431d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid}
441d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
451d21d2f9bb82889781b4be087ad65ba488608866Dylan Reidstatic int play_buffer_error(struct cras_client *client,
461d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			     cras_stream_id_t stream_id,
471d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			     int error,
481d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			     void *user_arg)
491d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid{
501d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	free(user_arg);
511d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	return 0;
521d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid}
531d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
541d21d2f9bb82889781b4be087ad65ba488608866Dylan Reidint cras_helper_create_connect(struct cras_client **client)
551d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid{
561d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	int rc;
571d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
581d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	rc = cras_client_create(client);
591d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	if (rc < 0)
601d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid		return rc;
611d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
621d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	rc = cras_client_connect(*client);
631d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	if (rc < 0)
641d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid		goto client_start_error;
651d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
661d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	rc = cras_client_run_thread(*client);
671d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	if (rc < 0)
681d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid		goto client_start_error;
691d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
701d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	rc = cras_client_connected_wait(*client);
711d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	if (rc < 0)
721d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid		goto client_start_error;
731d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
741d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	return 0;
751d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
761d21d2f9bb82889781b4be087ad65ba488608866Dylan Reidclient_start_error:
771d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	cras_client_destroy(*client);
781d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	return rc;
791d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid}
801d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
811d21d2f9bb82889781b4be087ad65ba488608866Dylan Reidint cras_helper_add_stream_simple(struct cras_client *client,
821d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				  enum CRAS_STREAM_DIRECTION direction,
831d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				  void *user_data,
841d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				  cras_unified_cb_t unified_cb,
851d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				  cras_error_cb_t err_cb,
861d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				  snd_pcm_format_t format,
871d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				  unsigned int frame_rate,
881d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				  unsigned int num_channels,
891d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				  int dev_idx,
901d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid				  cras_stream_id_t *stream_id_out)
911d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid{
921d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	struct cras_audio_format *aud_format;
931d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	struct cras_stream_params *params;
941d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	int rc;
951d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
961d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	aud_format = cras_audio_format_create(format, frame_rate, num_channels);
971d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	if (!aud_format)
981d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid		return -ENOMEM;
991d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
1001d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	params = cras_client_unified_params_create(CRAS_STREAM_OUTPUT,
1011d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			2048, CRAS_STREAM_TYPE_DEFAULT, 0, user_data,
1021d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			unified_cb, err_cb, aud_format);
1031d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	if (!params) {
1041d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid		rc = -ENOMEM;
1051d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid		goto done_add_stream;
1061d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	}
1071d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
1081d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	if (dev_idx < 0)
1091d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid		dev_idx = NO_DEVICE;
1101d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	rc = cras_client_add_pinned_stream(client, dev_idx, stream_id_out,
1111d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid					   params);
1121d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
1131d21d2f9bb82889781b4be087ad65ba488608866Dylan Reiddone_add_stream:
1141d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	cras_audio_format_destroy(aud_format);
1151d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	cras_client_stream_params_destroy(params);
1161d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	return rc;
1171d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid}
1181d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
1191d21d2f9bb82889781b4be087ad65ba488608866Dylan Reidint cras_helper_play_buffer(struct cras_client *client,
120a6de2464f12ba758ee978ebe6b104c59757464a8Nathan Bullock			    const void *buffer,
1211d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			    unsigned int frames,
1221d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			    snd_pcm_format_t format,
1231d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			    unsigned int frame_rate,
1241d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			    unsigned int num_channels,
1251d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			    int dev_idx)
1261d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid{
1271d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	struct buffer_data *data;
1281d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	cras_stream_id_t stream_id;
1291d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
1301d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	data = malloc(sizeof(*data));
1311d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
1321d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	data->buffer = buffer;
1331d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	data->frame_bytes = num_channels *
1341d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			    snd_pcm_format_physical_width(format) / 8;
1351d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	data->offset = 0;
1361d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	data->len = frames * data->frame_bytes;
1371d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid
1381d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid	return cras_helper_add_stream_simple(client, CRAS_STREAM_OUTPUT, data,
1391d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			play_buffer_callback, play_buffer_error, format,
1401d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid			frame_rate, num_channels, dev_idx, &stream_id);
1411d21d2f9bb82889781b4be087ad65ba488608866Dylan Reid}
142