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