1/* Copyright (c) 2015 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 * This example plays a file.  The filename is the only argument.  The file is
6 * assumed to contain raw stereo 16-bit PCM data to be played at 48kHz.
7 * usage:  cplay <filename>
8 */
9
10#include <cras_client.h>
11#include <cras_helpers.h>
12#include <stdio.h>
13#include <stdint.h>
14
15/* Used as a cookie for the playing stream. */
16struct stream_data {
17	int fd;
18	unsigned int frame_bytes;
19};
20
21/* Run from callback thread. */
22static int put_samples(struct cras_client *client,
23		       cras_stream_id_t stream_id,
24		       uint8_t *captured_samples,
25		       uint8_t *playback_samples,
26		       unsigned int frames,
27		       const struct timespec *captured_time,
28		       const struct timespec *playback_time,
29		       void *user_arg)
30{
31	struct stream_data *data = (struct stream_data *)user_arg;
32	int nread;
33
34	nread = read(data->fd, playback_samples, frames * data->frame_bytes);
35	if (nread <= 0)
36		return EOF;
37
38	return nread / data->frame_bytes;
39}
40
41/* Run from callback thread. */
42static int stream_error(struct cras_client *client,
43			cras_stream_id_t stream_id,
44			int err,
45			void *arg)
46{
47	printf("Stream error %d\n", err);
48	exit(err);
49	return 0;
50}
51
52int main(int argc, char **argv)
53{
54	struct cras_client *client;
55	cras_stream_id_t stream_id;
56	struct stream_data *data;
57	int rc = 0;
58	int fd;
59	const unsigned int block_size = 4800;
60	const unsigned int num_channels = 2;
61	const unsigned int rate = 48000;
62	const unsigned int flags = 0;
63
64	if (argc < 2)
65		printf("Usage: %s filename\n", argv[0]);
66
67	fd = open(argv[1], O_RDONLY);
68	if (fd < 0) {
69		perror("failed to open file");
70		return -errno;
71	}
72
73	rc = cras_helper_create_connect(&client);
74	if (rc < 0) {
75		fprintf(stderr, "Couldn't create client.\n");
76		close(fd);
77		return rc;
78	}
79
80	data = malloc(sizeof(*data));
81	data->fd = fd;
82	data->frame_bytes = 4;
83
84	rc = cras_helper_add_stream_simple(client, CRAS_STREAM_OUTPUT, data,
85			put_samples, stream_error, SND_PCM_FORMAT_S16_LE, rate,
86			num_channels, NO_DEVICE, &stream_id);
87	if (rc < 0) {
88		fprintf(stderr, "adding a stream %d\n", rc);
89		goto destroy_exit;
90	}
91
92	/* At this point the stream has been added and audio callbacks will
93	 * start to fire.  This app can now go off and do other things, but this
94	 * example just loops forever. */
95	while (1) {
96		sleep(1);
97	}
98
99destroy_exit:
100	cras_client_destroy(client);
101	close(fd);
102	free(data);
103	return rc;
104}
105