summaryrefslogtreecommitdiff
path: root/cras/examples/cplay.c
blob: eb6d8e6c646cace0bf98d81fbdda57d5c5395208 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* Copyright (c) 2015 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.
 *
 * This example plays a file.  The filename is the only argument.  The file is
 * assumed to contain raw stereo 16-bit PCM data to be played at 48kHz.
 * usage:  cplay <filename>
 */

#include <cras_client.h>
#include <cras_helpers.h>
#include <stdio.h>
#include <stdint.h>

/* Used as a cookie for the playing stream. */
struct stream_data {
	int fd;
	unsigned int frame_bytes;
};

/* Run from callback thread. */
static int put_samples(struct cras_client *client, cras_stream_id_t stream_id,
		       uint8_t *captured_samples, uint8_t *playback_samples,
		       unsigned int frames,
		       const struct timespec *captured_time,
		       const struct timespec *playback_time, void *user_arg)
{
	struct stream_data *data = (struct stream_data *)user_arg;
	int nread;

	nread = read(data->fd, playback_samples, frames * data->frame_bytes);
	if (nread <= 0)
		return EOF;

	return nread / data->frame_bytes;
}

/* Run from callback thread. */
static int stream_error(struct cras_client *client, cras_stream_id_t stream_id,
			int err, void *arg)
{
	printf("Stream error %d\n", err);
	exit(err);
	return 0;
}

int main(int argc, char **argv)
{
	struct cras_client *client;
	cras_stream_id_t stream_id;
	struct stream_data *data;
	int rc = 0;
	int fd;
	const unsigned int block_size = 4800;
	const unsigned int num_channels = 2;
	const unsigned int rate = 48000;
	const unsigned int flags = 0;

	if (argc < 2)
		printf("Usage: %s filename\n", argv[0]);

	fd = open(argv[1], O_RDONLY);
	if (fd < 0) {
		perror("failed to open file");
		return -errno;
	}

	rc = cras_helper_create_connect(&client);
	if (rc < 0) {
		fprintf(stderr, "Couldn't create client.\n");
		close(fd);
		return rc;
	}

	data = malloc(sizeof(*data));
	data->fd = fd;
	data->frame_bytes = 4;

	rc = cras_helper_add_stream_simple(client, CRAS_STREAM_OUTPUT, data,
					   put_samples, stream_error,
					   SND_PCM_FORMAT_S16_LE, rate,
					   num_channels, NO_DEVICE, &stream_id);
	if (rc < 0) {
		fprintf(stderr, "adding a stream %d\n", rc);
		goto destroy_exit;
	}

	/* At this point the stream has been added and audio callbacks will
	 * start to fire.  This app can now go off and do other things, but this
	 * example just loops forever. */
	while (1) {
		sleep(1);
	}

destroy_exit:
	cras_client_destroy(client);
	close(fd);
	free(data);
	return rc;
}