⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trident_synth.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
static void event_private1(snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v){	if (v->sample_ops && v->sample_ops->sample_private1)		v->sample_ops->sample_private1(p->trident, v, (unsigned char *) &ev->data.sample.param.raw8);}typedef void (trident_sample_event_handler_t) (snd_seq_event_t * ev, snd_trident_port_t * p, snd_trident_voice_t * v);static trident_sample_event_handler_t *trident_sample_event_handlers[9] ={	event_sample,	event_cluster,	event_start,	event_stop,	event_freq,	event_volume,	event_loop,	event_position,	event_private1};static void snd_trident_sample_event(snd_seq_event_t * ev, snd_trident_port_t * p){	int idx, voice;	trident_t *trident = p->trident;	snd_trident_voice_t *v;	unsigned long flags;	idx = ev->type - SNDRV_SEQ_EVENT_SAMPLE;	if (idx < 0 || idx > 8)		return;	for (voice = 0; voice < 64; voice++) {		v = &trident->synth.voices[voice];		if (v->use && v->client == ev->source.client &&		    v->port == ev->source.port &&		    v->index == ev->data.sample.channel) {			spin_lock_irqsave(&trident->event_lock, flags);			trident_sample_event_handlers[idx] (ev, p, v);			spin_unlock_irqrestore(&trident->event_lock, flags);			return;		}	}}/* */static void snd_trident_synth_free_voices(trident_t * trident, int client, int port){	int idx;	snd_trident_voice_t *voice;	for (idx = 0; idx < 32; idx++) {		voice = &trident->synth.voices[idx];		if (voice->use && voice->client == client && voice->port == port)			snd_trident_free_voice(trident, voice);	}}static int snd_trident_synth_use(void *private_data, snd_seq_port_subscribe_t * info){	snd_trident_port_t *port = (snd_trident_port_t *) private_data;	trident_t *trident = port->trident;	snd_trident_voice_t *voice;	unsigned int idx;	unsigned long flags;	if (info->voices > 32)		return -EINVAL;	spin_lock_irqsave(&trident->reg_lock, flags);	for (idx = 0; idx < info->voices; idx++) {		voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_SYNTH, info->sender.client, info->sender.port);		if (voice == NULL) {			snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port);			spin_unlock_irqrestore(&trident->reg_lock, flags);			return -EBUSY;		}		voice->index = idx;		voice->Vol = 0x3ff;		voice->EC = 0x0fff;	}#if 0	for (idx = 0; idx < info->midi_voices; idx++) {		port->midi_has_voices = 1;		voice = snd_trident_alloc_voice(trident, SNDRV_TRIDENT_VOICE_TYPE_MIDI, info->sender.client, info->sender.port);		if (voice == NULL) {			snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port);			spin_unlock_irqrestore(&trident->reg_lock, flags);			return -EBUSY;		}		voice->Vol = 0x3ff;		voice->EC = 0x0fff;	}#endif	spin_unlock_irqrestore(&trident->reg_lock, flags);	return 0;}static int snd_trident_synth_unuse(void *private_data, snd_seq_port_subscribe_t * info){	snd_trident_port_t *port = (snd_trident_port_t *) private_data;	trident_t *trident = port->trident;	unsigned long flags;	spin_lock_irqsave(&trident->reg_lock, flags);	snd_trident_synth_free_voices(trident, info->sender.client, info->sender.port);	spin_unlock_irqrestore(&trident->reg_lock, flags);	return 0;}/* */static void snd_trident_synth_free_private_instruments(snd_trident_port_t * p, int client){	snd_seq_instr_header_t ifree;	memset(&ifree, 0, sizeof(ifree));	ifree.cmd = SNDRV_SEQ_INSTR_FREE_CMD_PRIVATE;	snd_seq_instr_list_free_cond(p->trident->synth.ilist, &ifree, client, 0);}static int snd_trident_synth_event_input(snd_seq_event_t * ev, int direct, void *private_data, int atomic, int hop){	snd_trident_port_t *p = (snd_trident_port_t *) private_data;	if (p == NULL)		return -EINVAL;	if (ev->type >= SNDRV_SEQ_EVENT_SAMPLE &&	    ev->type <= SNDRV_SEQ_EVENT_SAMPLE_PRIVATE1) {		snd_trident_sample_event(ev, p);		return 0;	}	if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM &&	    ev->source.port == SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE) {		if (ev->type == SNDRV_SEQ_EVENT_CLIENT_EXIT) {			snd_trident_synth_free_private_instruments(p, ev->data.addr.client);			return 0;		}	}	if (direct) {		if (ev->type >= SNDRV_SEQ_EVENT_INSTR_BEGIN) {			snd_seq_instr_event(&p->trident->synth.simple_ops.kops,					    p->trident->synth.ilist, ev,					    p->trident->synth.seq_client, atomic, hop);			return 0;		}	}	return 0;}static void snd_trident_synth_instr_notify(void *private_data,					   snd_seq_kinstr_t * instr,					   int what){	int idx;	trident_t *trident = private_data;	snd_trident_voice_t *pvoice;	unsigned long flags;	spin_lock_irqsave(&trident->event_lock, flags);	for (idx = 0; idx < 64; idx++) {		pvoice = &trident->synth.voices[idx];		if (pvoice->use && !memcmp(&pvoice->instr, &instr->instr, sizeof(pvoice->instr))) {			if (pvoice->sample_ops && pvoice->sample_ops->sample_stop) {				pvoice->sample_ops->sample_stop(trident, pvoice, SAMPLE_STOP_IMMEDIATELY);			} else {				snd_trident_stop_voice(trident, pvoice->number);				pvoice->flags &= ~SNDRV_TRIDENT_VFLG_RUNNING;			}		}	}	spin_unlock_irqrestore(&trident->event_lock, flags);}/* */static void snd_trident_synth_free_port(void *private_data){	snd_trident_port_t *p = (snd_trident_port_t *) private_data;	if (p)		snd_midi_channel_free_set(p->chset);}static int snd_trident_synth_create_port(trident_t * trident, int idx){	snd_trident_port_t *p;	snd_seq_port_callback_t callbacks;	char name[32];	char *str;	int result;	p = &trident->synth.seq_ports[idx];	p->chset = snd_midi_channel_alloc_set(16);	if (p->chset == NULL)		return -ENOMEM;	p->chset->private_data = p;	p->trident = trident;	p->client = trident->synth.seq_client;	memset(&callbacks, 0, sizeof(callbacks));	callbacks.owner = THIS_MODULE;	callbacks.use = snd_trident_synth_use;	callbacks.unuse = snd_trident_synth_unuse;	callbacks.event_input = snd_trident_synth_event_input;	callbacks.private_free = snd_trident_synth_free_port;	callbacks.private_data = p;	str = "???";	switch (trident->device) {	case TRIDENT_DEVICE_ID_DX:	str = "Trident 4DWave-DX"; break;	case TRIDENT_DEVICE_ID_NX:	str = "Trident 4DWave-NX"; break;	case TRIDENT_DEVICE_ID_SI7018:	str = "SiS 7018"; break;	}	sprintf(name, "%s port %i", str, idx);	p->chset->port = snd_seq_event_port_attach(trident->synth.seq_client,						   &callbacks,						   SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE,						   SNDRV_SEQ_PORT_TYPE_DIRECT_SAMPLE |						   SNDRV_SEQ_PORT_TYPE_SYNTH,						   16, 0,						   name);	if (p->chset->port < 0) {		result = p->chset->port;		snd_trident_synth_free_port(p);		return result;	}	p->port = p->chset->port;	return 0;}/* */static int snd_trident_synth_new_device(snd_seq_device_t *dev){	trident_t *trident;	int client, i;	snd_seq_client_callback_t callbacks;	snd_seq_client_info_t cinfo;	snd_seq_port_subscribe_t sub;	snd_simple_ops_t *simpleops;	char *str;	trident = *(trident_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);	if (trident == NULL)		return -EINVAL;	trident->synth.seq_client = -1;	/* allocate new client */	memset(&callbacks, 0, sizeof(callbacks));	callbacks.private_data = trident;	callbacks.allow_output = callbacks.allow_input = 1;	client = trident->synth.seq_client =	    snd_seq_create_kernel_client(trident->card, 1, &callbacks);	if (client < 0)		return client;	/* change name of client */	memset(&cinfo, 0, sizeof(cinfo));	cinfo.client = client;	cinfo.type = KERNEL_CLIENT;	str = "???";	switch (trident->device) {	case TRIDENT_DEVICE_ID_DX:	str = "Trident 4DWave-DX"; break;	case TRIDENT_DEVICE_ID_NX:	str = "Trident 4DWave-NX"; break;	case TRIDENT_DEVICE_ID_SI7018:	str = "SiS 7018"; break;	}	sprintf(cinfo.name, str);	snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);	for (i = 0; i < 4; i++)		snd_trident_synth_create_port(trident, i);	trident->synth.ilist = snd_seq_instr_list_new();	if (trident->synth.ilist == NULL) {		snd_seq_delete_kernel_client(client);		trident->synth.seq_client = -1;		return -ENOMEM;	}	trident->synth.ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT;	simpleops = &trident->synth.simple_ops;	snd_seq_simple_init(simpleops, trident, NULL);	simpleops->put_sample = snd_trident_simple_put_sample;	simpleops->get_sample = snd_trident_simple_get_sample;	simpleops->remove_sample = snd_trident_simple_remove_sample;	simpleops->notify = snd_trident_synth_instr_notify;	memset(&sub, 0, sizeof(sub));	sub.sender.client = SNDRV_SEQ_CLIENT_SYSTEM;	sub.sender.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;	sub.dest.client = client;	sub.dest.port = 0;	snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, &sub);	return 0;}static int snd_trident_synth_delete_device(snd_seq_device_t *dev){	trident_t *trident;	trident = *(trident_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);	if (trident == NULL)		return -EINVAL;	if (trident->synth.seq_client >= 0) {		snd_seq_delete_kernel_client(trident->synth.seq_client);		trident->synth.seq_client = -1;	}	if (trident->synth.ilist)		snd_seq_instr_list_free(&trident->synth.ilist);	return 0;}static int __init alsa_trident_synth_init(void){	static snd_seq_dev_ops_t ops =	{		snd_trident_synth_new_device,		snd_trident_synth_delete_device	};	return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_TRIDENT, &ops,					      sizeof(trident_t*));}static void __exit alsa_trident_synth_exit(void){	snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_TRIDENT);}module_init(alsa_trident_synth_init)module_exit(alsa_trident_synth_exit)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -