/* Copyright (c) 2012 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.
 */

#include <alsa/asoundlib.h>
#include <alsa/control_external.h>
#include <cras_client.h>

static const size_t MAX_IODEVS = 10; /* Max devices to print out. */
static const size_t MAX_IONODES = 20; /* Max ionodes to print out. */

/* Support basic input/output volume/mute only. */
enum CTL_CRAS_MIXER_CONTROLS {
	CTL_CRAS_MIXER_PLAYBACK_SWITCH,
	CTL_CRAS_MIXER_PLAYBACK_VOLUME,
	NUM_CTL_CRAS_MIXER_ELEMS
};

/* Hold info specific to each control. */
struct cras_mixer_control {
	const char *name;
	int type;
	unsigned int access;
	unsigned int count;
};

/* CRAS mixer elements. */
static const struct cras_mixer_control cras_elems[NUM_CTL_CRAS_MIXER_ELEMS] = {
	{ "Master Playback Switch", SND_CTL_ELEM_TYPE_BOOLEAN,
	  SND_CTL_EXT_ACCESS_READWRITE, 1 },
	{ "Master Playback Volume", SND_CTL_ELEM_TYPE_INTEGER,
	  SND_CTL_EXT_ACCESS_READWRITE, 1 },
};

/* Holds the client and ctl plugin pointers. */
struct ctl_cras {
	snd_ctl_ext_t ext_ctl;
	struct cras_client *client;
};

/* Frees resources when the plugin is closed. */
static void ctl_cras_close(snd_ctl_ext_t *ext_ctl)
{
	struct ctl_cras *cras = (struct ctl_cras *)ext_ctl->private_data;

	if (cras) {
		cras_client_stop(cras->client);
		cras_client_destroy(cras->client);
	}
	free(cras);
}

/* Lists available controls. */
static int ctl_cras_elem_list(snd_ctl_ext_t *ext_ctl, unsigned int offset,
			      snd_ctl_elem_id_t *id)
{
	snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
	if (offset >= NUM_CTL_CRAS_MIXER_ELEMS)
		return -EINVAL;
	snd_ctl_elem_id_set_name(id, cras_elems[offset].name);
	return 0;
}

/* Returns the number of available controls. */
static int ctl_cras_elem_count(snd_ctl_ext_t *ext_ctl)
{
	return NUM_CTL_CRAS_MIXER_ELEMS;
}

/* Gets a control key from a search id. */
static snd_ctl_ext_key_t ctl_cras_find_elem(snd_ctl_ext_t *ext_ctl,
					    const snd_ctl_elem_id_t *id)
{
	const char *name;
	unsigned int numid;

	numid = snd_ctl_elem_id_get_numid(id);
	if (numid - 1 < NUM_CTL_CRAS_MIXER_ELEMS)
		return numid - 1;

	name = snd_ctl_elem_id_get_name(id);

	for (numid = 0; numid < NUM_CTL_CRAS_MIXER_ELEMS; numid++)
		if (strcmp(cras_elems[numid].name, name) == 0)
			return numid;

	return SND_CTL_EXT_KEY_NOT_FOUND;
}

/* Fills accessibility, type and count based on the specified control. */
static int ctl_cras_get_attribute(snd_ctl_ext_t *ext_ctl, snd_ctl_ext_key_t key,
				  int *type, unsigned int *acc,
				  unsigned int *count)
{
	if (key >= NUM_CTL_CRAS_MIXER_ELEMS)
		return -EINVAL;
	*type = cras_elems[key].type;
	*acc = cras_elems[key].access;
	*count = cras_elems[key].count;
	return 0;
}

/* Returns the range of the specified control.  The volume sliders always run
 * from 0 to 100 for CRAS. */
static int ctl_cras_get_integer_info(snd_ctl_ext_t *ext_ctl,
				     snd_ctl_ext_key_t key, long *imin,
				     long *imax, long *istep)
{
	*istep = 0;
	*imin = 0;
	*imax = 100;
	return 0;
}

static int get_nodes(struct cras_client *client, enum CRAS_STREAM_DIRECTION dir,
		     struct cras_ionode_info *nodes, size_t num_nodes)
{
	struct cras_iodev_info devs[MAX_IODEVS];
	size_t num_devs;
	int rc;

	if (dir == CRAS_STREAM_OUTPUT)
		rc = cras_client_get_output_devices(client, devs, nodes,
						    &num_devs, &num_nodes);
	else
		rc = cras_client_get_input_devices(client, devs, nodes,
						   &num_devs, &num_nodes);
	if (rc < 0)
		return 0;
	return num_nodes;
}

/* Gets the value of the given control from CRAS and puts it in value. */
static int ctl_cras_read_integer(snd_ctl_ext_t *ext_ctl, snd_ctl_ext_key_t key,
				 long *value)
{
	struct ctl_cras *cras = (struct ctl_cras *)ext_ctl->private_data;
	struct cras_ionode_info nodes[MAX_IONODES];
	int num_nodes, i;

	switch (key) {
	case CTL_CRAS_MIXER_PLAYBACK_SWITCH:
		*value = !cras_client_get_user_muted(cras->client);
		break;
	case CTL_CRAS_MIXER_PLAYBACK_VOLUME:
		num_nodes = get_nodes(cras->client, CRAS_STREAM_OUTPUT, nodes,
				      MAX_IONODES);
		for (i = 0; i < num_nodes; i++) {
			if (!nodes[i].active)
				continue;
			*value = nodes[i].volume;
			break;
		}
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

/* Writes the given values to CRAS. */
static int ctl_cras_write_integer(snd_ctl_ext_t *ext_ctl, snd_ctl_ext_key_t key,
				  long *value)
{
	struct ctl_cras *cras = (struct ctl_cras *)ext_ctl->private_data;
	struct cras_ionode_info nodes[MAX_IONODES];
	int num_nodes, i;

	switch (key) {
	case CTL_CRAS_MIXER_PLAYBACK_SWITCH:
		cras_client_set_user_mute(cras->client, !(*value));
		break;
	case CTL_CRAS_MIXER_PLAYBACK_VOLUME:
		num_nodes = get_nodes(cras->client, CRAS_STREAM_OUTPUT, nodes,
				      MAX_IONODES);
		for (i = 0; i < num_nodes; i++) {
			if (!nodes[i].active)
				continue;
			cras_client_set_node_volume(
				cras->client,
				cras_make_node_id(nodes[i].iodev_idx,
						  nodes[i].ionode_idx),
				*value);
		}
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static const snd_ctl_ext_callback_t ctl_cras_ext_callback = {
	.close = ctl_cras_close,
	.elem_count = ctl_cras_elem_count,
	.elem_list = ctl_cras_elem_list,
	.find_elem = ctl_cras_find_elem,
	.get_attribute = ctl_cras_get_attribute,
	.get_integer_info = ctl_cras_get_integer_info,
	.read_integer = ctl_cras_read_integer,
	.write_integer = ctl_cras_write_integer,
};

SND_CTL_PLUGIN_DEFINE_FUNC(cras)
{
	struct ctl_cras *cras;
	int rc;

	cras = malloc(sizeof(*cras));
	if (cras == NULL)
		return -ENOMEM;

	rc = cras_client_create(&cras->client);
	if (rc != 0 || cras->client == NULL) {
		fprintf(stderr, "Couldn't create CRAS client\n");
		free(cras);
		return rc;
	}

	rc = cras_client_connect(cras->client);
	if (rc < 0) {
		fprintf(stderr, "Couldn't connect to cras.\n");
		cras_client_destroy(cras->client);
		free(cras);
		return rc;
	}

	rc = cras_client_run_thread(cras->client);
	if (rc < 0) {
		fprintf(stderr, "Couldn't start client thread.\n");
		cras_client_stop(cras->client);
		cras_client_destroy(cras->client);
		free(cras);
		return rc;
	}

	rc = cras_client_connected_wait(cras->client);
	if (rc < 0) {
		fprintf(stderr, "CRAS client wouldn't connect.\n");
		cras_client_stop(cras->client);
		cras_client_destroy(cras->client);
		free(cras);
		return rc;
	}

	cras->ext_ctl.version = SND_CTL_EXT_VERSION;
	cras->ext_ctl.card_idx = 0;
	strncpy(cras->ext_ctl.id, "cras", sizeof(cras->ext_ctl.id) - 1);
	cras->ext_ctl.id[sizeof(cras->ext_ctl.id) - 1] = '\0';
	strncpy(cras->ext_ctl.driver, "CRAS plugin",
		sizeof(cras->ext_ctl.driver) - 1);
	cras->ext_ctl.driver[sizeof(cras->ext_ctl.driver) - 1] = '\0';
	strncpy(cras->ext_ctl.name, "CRAS", sizeof(cras->ext_ctl.name) - 1);
	cras->ext_ctl.name[sizeof(cras->ext_ctl.name) - 1] = '\0';
	strncpy(cras->ext_ctl.longname, "CRAS",
		sizeof(cras->ext_ctl.longname) - 1);
	cras->ext_ctl.longname[sizeof(cras->ext_ctl.longname) - 1] = '\0';
	strncpy(cras->ext_ctl.mixername, "CRAS",
		sizeof(cras->ext_ctl.mixername) - 1);
	cras->ext_ctl.mixername[sizeof(cras->ext_ctl.mixername) - 1] = '\0';
	cras->ext_ctl.poll_fd = -1;

	cras->ext_ctl.callback = &ctl_cras_ext_callback;
	cras->ext_ctl.private_data = cras;

	rc = snd_ctl_ext_create(&cras->ext_ctl, name, mode);
	if (rc < 0) {
		cras_client_stop(cras->client);
		cras_client_destroy(cras->client);
		free(cras);
		return rc;
	}

	*handlep = cras->ext_ctl.handle;
	return 0;
}

SND_CTL_PLUGIN_SYMBOL(cras);
