/*
 *   Generic MIDI synth driver for ALSA sequencer
 *   Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
 *                         Jaroslav Kysela <perex@suse.cz>
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 *
 */
 
/* 
Possible options for midisynth module:
	- automatic opening of midi ports on first received event or subscription
	  (close will be performed when client leaves)
*/


#include <sound/driver.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/moduleparam.h>
#include <asm/semaphore.h>
#include <sound/core.h>
#include <sound/rawmidi.h>
#include <sound/seq_kernel.h>
#include <sound/seq_device.h>
#include <sound/seq_midi_event.h>
#include <sound/initval.h>

MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI synth.");
MODULE_LICENSE("GPL");
static int output_buffer_size = PAGE_SIZE;
module_param(output_buffer_size, int, 0644);
MODULE_PARM_DESC(output_buffer_size, "Output buffer size in bytes.");
static int input_buffer_size = PAGE_SIZE;
module_param(input_buffer_size, int, 0644);
MODULE_PARM_DESC(input_buffer_size, "Input buffer size in bytes.");

/* data for this midi synth driver */
typedef struct {
	snd_card_t *card;
	int device;
	int subdevice;
	snd_rawmidi_file_t input_rfile;
	snd_rawmidi_file_t output_rfile;
	int seq_client;
	int seq_port;
	snd_midi_event_t *parser;
} seq_midisynth_t;

typedef struct {
	int seq_client;
	int num_ports;
	int ports_per_device[SNDRV_RAWMIDI_DEVICES];
 	seq_midisynth_t *ports[SNDRV_RAWMIDI_DEVICES];
} seq_midisynth_client_t;

static seq_midisynth_client_t *synths[SNDRV_CARDS];
static DECLARE_MUTEX(register_mutex);

/* handle rawmidi input event (MIDI v1.0 stream) */
static void snd_midi_input_event(snd_rawmidi_substream_t * substream)
{
	snd_rawmidi_runtime_t *runtime;
	seq_midisynth_t *msynth;
	snd_seq_event_t ev;
	char buf[16], *pbuf;
	long res, count;

	if (substream == NULL)
		return;
	runtime = substream->runtime;
	msynth = (seq_midisynth_t *) runtime->private_data;
	if (msynth == NULL)
		return;
	memset(&ev, 0, sizeof(ev));
	while (runtime->avail > 0) {
		res = snd_rawmidi_kernel_read(substream, buf, sizeof(buf));
		if (res <= 0)
			continue;
		if (msynth->parser == NULL)
			continue;
		pbuf = buf;
		while (res > 0) {
			count = snd_midi_event_encode(msynth->parser, pbuf, res, &ev);
			if (count < 0)
				break;
			pbuf += count;
			res -= count;
			if (ev.type != SNDRV_SEQ_EVENT_NONE) {
				ev.source.port = msynth->seq_port;
				ev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
				snd_seq_kernel_client_dispatch(msynth->seq_client, &ev, 1, 0);
				/* clear event and reset header */
				memset(&ev, 0, sizeof(ev));
			}
		}
	}
}

static int dump_midi(snd_rawmidi_substream_t *substream, const char *buf, int count)
{
	snd_rawmidi_runtime_t *runtime;
	int tmp;

	snd_assert(substream != NULL || buf != NULL, return -EINVAL);
	runtime = substream->runtime;
	if ((tmp = runtime->avail) < count) {
		snd_printd("warning, output event was lost (count = %i, available = %i)\n", count, tmp);
		return -ENOMEM;
	}
	if (snd_rawmidi_kernel_write(substream, buf, count) < count)
		return -EINVAL;
	return 0;
}

static int event_process_midi(snd_seq_event_t * ev, int direct,
			      void *private_data, int atomic, int hop)
{
	seq_midisynth_t *msynth = (seq_midisynth_t *) private_data;
	unsigned char msg[10];	/* buffer for constructing midi messages */
	snd_rawmidi_substream_t *substream;
	int res;

	snd_assert(msynth != NULL, return -EINVAL);
	substream = msynth->output_rfile.output;
	if (substream == NULL)
		return -ENODEV;
	if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {	/* special case, to save space */
		if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) {
			/* invalid event */
			snd_printd("seq_midi: invalid sysex event flags = 0x%x\n", ev->flags);
			return 0;
		}
		res = snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream);
		snd_midi_event_reset_decode(msynth->parser);
		if (res < 0)
			return res;
	} else {
		if (msynth->parser == NULL)
			return -EIO;
		res = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev);
		if (res < 0)
			return res;
		if ((res = dump_midi(substream, msg, res)) < 0) {
			snd_midi_event_reset_decode(msynth->parser);
			return res;
		}
	}
	return 0;
}


static int snd_seq_midisynth_new(seq_midisynth_t *msynth,
				 snd_card_t *card,
				 int device,
				 int subdevice)
{
	if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &msynth->parser) < 0)
		return -ENOMEM;
	msynth->card = card;
	msynth->device = device;
	msynth->subdevice = subdevice;
	return 0;
}

/* open associated midi device for input */
static int midisynth_subscribe(void *private_data, snd_seq_port_subscribe_t *info)
{
	int err;
	seq_midisynth_t *msynth = (seq_midisynth_t *)private_data;
	snd_rawmidi_runtime_t *runtime;
	snd_rawmidi_params_t params;

	/* open midi port */
	if ((err = snd_rawmidi_kernel_open(msynth->card->number, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_INPUT, &msynth->input_rfile)) < 0) {
		snd_printd("midi input open failed!!!\n");
		return err;
	}
	runtime = msynth->input_rfile.input->runtime;
	memset(&params, 0, sizeof(params));
	params.avail_min = 1;
	params.buffer_size = input_buffer_size;
	if ((err = snd_rawmidi_input_params(msynth->input_rfile.input, &params)) < 0) {
		snd_rawmidi_kernel_release(&msynth->input_rfile);
		return err;
	}
	snd_midi_event_reset_encode(msynth->parser);
	runtime->event = snd_midi_input_event;
	runtime->private_data = msynth;
	snd_rawmidi_kernel_read(msynth->input_rfile.input, NULL, 0);
	return 0;
}

/* close associated midi device for input */
static int midisynth_unsubscribe(void *private_data, snd_seq_port_subscribe_t *info)
{
	int err;
	seq_midisynth_t *msynth = (seq_midisynth_t *)private_data;

	snd_assert(msynth->input_rfile.input != NULL, return -EINVAL);
	err = snd_rawmidi_kernel_release(&msynth->input_rfile);
	return err;
}

/* open associated midi device for output */
static int midisynth_use(void *private_data, snd_seq_port_subscribe_t *info)
{
	int err;
	seq_midisynth_t *msynth = (seq_midisynth_t *)private_data;
	snd_rawmidi_params_t params;

	/* open midi port */
	if ((err = snd_rawmidi_kernel_open(msynth->card->number, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_OUTPUT, &msynth->output_rfile)) < 0) {
		snd_printd("midi output open failed!!!\n");
		return err;
	}
	memset(&params, 0, sizeof(params));
	params.avail_min = 1;
	params.buffer_size = output_buffer_size;
	if ((err = snd_rawmidi_output_params(msynth->output_rfile.output, &params)) < 0) {
		snd_rawmidi_kernel_release(&msynth->output_rfile);
		return err;
	}
	snd_midi_event_reset_decode(msynth->parser);
	return 0;
}

/* close associated midi device for output */
static int midisynth_unuse(void *private_data, snd_seq_port_subscribe_t *info)
{
	seq_midisynth_t *msynth = (seq_midisynth_t *)private_data;
	unsigned char buf = 0xff; /* MIDI reset */

	snd_assert(msynth->output_rfile.output != NULL, return -EINVAL);
	/* sending single MIDI reset message to shut the device up */
	snd_rawmidi_kernel_write(msynth->output_rfile.output, &buf, 1);
	snd_rawmidi_drain_output(msynth->output_rfile.output);
	return snd_rawmidi_kernel_release(&msynth->output_rfile);
}

/* delete given midi synth port */
static void snd_seq_midisynth_delete(seq_midisynth_t *msynth)
{
	if (msynth == NULL)
		return;

	if (msynth->seq_client > 0) {
		/* delete port */
		snd_seq_event_port_detach(msynth->seq_client, msynth->seq_port);
	}

	if (msynth->parser)
		snd_midi_event_free(msynth->parser);
}

/* set our client name */
static int set_client_name(seq_midisynth_client_t *client, snd_card_t *card,
			   snd_rawmidi_info_t *rmidi)
{
	snd_seq_client_info_t cinfo;
	const char *name;

	memset(&cinfo, 0, sizeof(cinfo));
	cinfo.client = client->seq_client;
	cinfo.type = KERNEL_CLIENT;
	name = rmidi->name[0] ? (const char *)rmidi->name : "External MIDI";
	strlcpy(cinfo.name, name, sizeof(cinfo.name));
	return snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
}

/* register new midi synth port */
static int
snd_seq_midisynth_register_port(snd_seq_device_t *dev)
{
	seq_midisynth_client_t *client;
	seq_midisynth_t *msynth, *ms;
	snd_seq_port_info_t *port;
	snd_rawmidi_info_t *info;
	int newclient = 0;
	unsigned int p, ports;
	snd_seq_client_callback_t callbacks;
	snd_seq_port_callback_t pcallbacks;
	snd_card_t *card = dev->card;
	int device = dev->device;
	unsigned int input_count = 0, output_count = 0;

	snd_assert(card != NULL && device >= 0 && device < SNDRV_RAWMIDI_DEVICES, return -EINVAL);
	info = kmalloc(sizeof(*info), GFP_KERNEL);
	if (! info)
		return -ENOMEM;
	info->device = device;
	info->stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
	info->subdevice = 0;
	if (snd_rawmidi_info_select(card, info) >= 0)
		output_count = info->subdevices_count;
	info->stream = SNDRV_RAWMIDI_STREAM_INPUT;
	if (snd_rawmidi_info_select(card, info) >= 0) {
		input_count = info->subdevices_count;
	}
	ports = output_count;
	if (ports < input_count)
		ports = input_count;
	if (ports == 0) {
		kfree(info);
		return -ENODEV;
	}
	if (ports > (256 / SNDRV_RAWMIDI_DEVICES))
		ports = 256 / SNDRV_RAWMIDI_DEVICES;

	down(&register_mutex);
	client = synths[card->number];
	if (client == NULL) {
		newclient = 1;
		client = kcalloc(1, sizeof(*client), GFP_KERNEL);
		if (client == NULL) {
			up(&register_mutex);
			kfree(info);
			return -ENOMEM;
		}
		memset(&callbacks, 0, sizeof(callbacks));
		callbacks.private_data = client;
		callbacks.allow_input = callbacks.allow_output = 1;
		client->seq_client = snd_seq_create_kernel_client(card, 0, &callbacks);
		if (client->seq_client < 0) {
			kfree(client);
			up(&register_mutex);
			kfree(info);
			return -ENOMEM;
		}
		set_client_name(client, card, info);
	} else if (device == 0)
		set_client_name(client, card, info); /* use the first device's name */

	msynth = kcalloc(ports, sizeof(seq_midisynth_t), GFP_KERNEL);
	port = kmalloc(sizeof(*port), GFP_KERNEL);
	if (msynth == NULL || port == NULL)
		goto __nomem;

	for (p = 0; p < ports; p++) {
		ms = &msynth[p];

		if (snd_seq_midisynth_new(ms, card, device, p) < 0)
			goto __nomem;

		/* declare port */
		memset(port, 0, sizeof(*port));
		port->addr.client = client->seq_client;
		port->addr.port = device * (256 / SNDRV_RAWMIDI_DEVICES) + p;
		port->flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT;
		memset(info, 0, sizeof(*info));
		info->device = device;
		if (p < output_count)
			info->stream = SNDRV_RAWMIDI_STREAM_OUTPUT;
		else
			info->stream = SNDRV_RAWMIDI_STREAM_INPUT;
		info->subdevice = p;
		if (snd_rawmidi_info_select(card, info) >= 0)
			strcpy(port->name, info->subname);
		if (! port->name[0]) {
			if (info->name[0]) {
				if (ports > 1)
					snprintf(port->name, sizeof(port->name), "%s-%d", info->name, p);
				else
					snprintf(port->name, sizeof(port->name), "%s", info->name);
			} else {
				/* last resort */
				if (ports > 1)
					sprintf(port->name, "MIDI %d-%d-%d", card->number, device, p);
				else
					sprintf(port->name, "MIDI %d-%d", card->number, device);
			}
		}
		if ((info->flags & SNDRV_RAWMIDI_INFO_OUTPUT) && p < output_count)
			port->capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE;
		if ((info->flags & SNDRV_RAWMIDI_INFO_INPUT) && p < input_count)
			port->capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ;
		if ((port->capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) &&
		    info->flags & SNDRV_RAWMIDI_INFO_DUPLEX)
			port->capability |= SNDRV_SEQ_PORT_CAP_DUPLEX;
		port->type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC;
		port->midi_channels = 16;
		memset(&pcallbacks, 0, sizeof(pcallbacks));
		pcallbacks.owner = THIS_MODULE;
		pcallbacks.private_data = ms;
		pcallbacks.subscribe = midisynth_subscribe;
		pcallbacks.unsubscribe = midisynth_unsubscribe;
		pcallbacks.use = midisynth_use;
		pcallbacks.unuse = midisynth_unuse;
		pcallbacks.event_input = event_process_midi;
		port->kernel = &pcallbacks;
		if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, port)<0)
			goto __nomem;
		ms->seq_client = client->seq_client;
		ms->seq_port = port->addr.port;
	}
	client->ports_per_device[device] = ports;
	client->ports[device] = msynth;
	client->num_ports++;
	if (newclient)
		synths[card->number] = client;
	up(&register_mutex);
	return 0;	/* success */

      __nomem:
	if (msynth != NULL) {
	      	for (p = 0; p < ports; p++)
	      		snd_seq_midisynth_delete(&msynth[p]);
		kfree(msynth);
	}
	if (newclient) {
		snd_seq_delete_kernel_client(client->seq_client);
		kfree(client);
	}
	kfree(info);
	kfree(port);
	up(&register_mutex);
	return -ENOMEM;
}

/* release midi synth port */
static int
snd_seq_midisynth_unregister_port(snd_seq_device_t *dev)
{
	seq_midisynth_client_t *client;
	seq_midisynth_t *msynth;
	snd_card_t *card = dev->card;
	int device = dev->device, p, ports;
	
	down(&register_mutex);
	client = synths[card->number];
	if (client == NULL || client->ports[device] == NULL) {
		up(&register_mutex);
		return -ENODEV;
	}
	ports = client->ports_per_device[device];
	client->ports_per_device[device] = 0;
	msynth = client->ports[device];
	client->ports[device] = NULL;
	snd_runtime_check(msynth != NULL || ports <= 0, goto __skip);
	for (p = 0; p < ports; p++)
		snd_seq_midisynth_delete(&msynth[p]);
	kfree(msynth);
      __skip:
	client->num_ports--;
	if (client->num_ports <= 0) {
		snd_seq_delete_kernel_client(client->seq_client);
		synths[card->number] = NULL;
		kfree(client);
	}
	up(&register_mutex);
	return 0;
}


static int __init alsa_seq_midi_init(void)
{
	static snd_seq_dev_ops_t ops = {
		snd_seq_midisynth_register_port,
		snd_seq_midisynth_unregister_port,
	};
	memset(&synths, 0, sizeof(synths));
	snd_seq_autoload_lock();
	snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH, &ops, 0);
	snd_seq_autoload_unlock();
	return 0;
}

static void __exit alsa_seq_midi_exit(void)
{
	snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_MIDISYNTH);
}

module_init(alsa_seq_midi_init)
module_exit(alsa_seq_midi_exit)
