예제 #1
0
static int snd_opl3_seq_new_device(struct snd_seq_device *dev)
{
	struct snd_opl3 *opl3;
	int client, err;
	char name[32];
	int opl_ver;

	opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
	if (opl3 == NULL)
		return -EINVAL;

	spin_lock_init(&opl3->voice_lock);

	opl3->seq_client = -1;

	/* allocate new client */
	opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8;
	sprintf(name, "OPL%i FM synth", opl_ver);
	client = opl3->seq_client =
		snd_seq_create_kernel_client(opl3->card, opl3->seq_dev_num,
					     name);
	if (client < 0)
		return client;

	if ((err = snd_opl3_synth_create_port(opl3)) < 0) {
		snd_seq_delete_kernel_client(client);
		opl3->seq_client = -1;
		return err;
	}

	/* initialize instrument list */
	opl3->ilist = snd_seq_instr_list_new();
	if (opl3->ilist == NULL) {
		snd_seq_delete_kernel_client(client);
		opl3->seq_client = -1;
		return -ENOMEM;
	}
	opl3->ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT;
	snd_seq_fm_init(&opl3->fm_ops, NULL);

	/* setup system timer */
	init_timer(&opl3->tlist);
	opl3->tlist.function = snd_opl3_timer_func;
	opl3->tlist.data = (unsigned long) opl3;
	spin_lock_init(&opl3->sys_timer_lock);
	opl3->sys_timer_status = 0;

#ifdef CONFIG_SND_SEQUENCER_OSS
	snd_opl3_init_seq_oss(opl3, name);
#endif
	return 0;
}
예제 #2
0
/*
 * register client and create ports
 */
static int __init
register_client(void)
{
	snd_seq_client_callback_t cb;
	snd_seq_client_info_t cinfo;
	snd_seq_dummy_port_t *rec1, *rec2;
	int i;

	if (ports < 1) {
		snd_printk(KERN_ERR "invalid number of ports %d\n", ports);
		return -EINVAL;
	}

	/* create client */
	memset(&cb, 0, sizeof(cb));
	cb.allow_input = 1;
	cb.allow_output = 1;
	my_client = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_DUMMY, &cb);
	if (my_client < 0)
		return my_client;

	/* set client name */
	memset(&cinfo, 0, sizeof(cinfo));
	cinfo.client = my_client;
	cinfo.type = KERNEL_CLIENT;
	strcpy(cinfo.name, "Midi Through");
	snd_seq_kernel_client_ctl(my_client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);

	/* create ports */
	for (i = 0; i < ports; i++) {
		rec1 = create_port(i, 0);
		if (rec1 == NULL) {
			snd_seq_delete_kernel_client(my_client);
			return -ENOMEM;
		}
		if (duplex) {
			rec2 = create_port(i, 1);
			if (rec2 == NULL) {
				snd_seq_delete_kernel_client(my_client);
				return -ENOMEM;
			}
			rec1->connect = rec2->port;
			rec2->connect = rec1->port;
		}
	}

	return 0;
}
예제 #3
0
/* release midi synth port */
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;
	}
	snd_seq_event_port_detach(client->seq_client, client->ports[device]->seq_port);
	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;
}
예제 #4
0
/* release midi synth port */
static int
snd_seq_midisynth_unregister_port(struct snd_seq_device *dev)
{
	struct seq_midisynth_client *client;
	struct seq_midisynth *msynth;
	struct snd_card *card = dev->card;
	int device = dev->device, p, ports;
	
	mutex_lock(&register_mutex);
	client = synths[card->number];
	if (client == NULL || client->ports[device] == NULL) {
		mutex_unlock(&register_mutex);
		return -ENODEV;
	}
	ports = client->ports_per_device[device];
	client->ports_per_device[device] = 0;
	msynth = client->ports[device];
	client->ports[device] = NULL;
	for (p = 0; p < ports; p++)
		snd_seq_midisynth_delete(&msynth[p]);
	kfree(msynth);
	client->num_ports--;
	if (client->num_ports <= 0) {
		snd_seq_delete_kernel_client(client->seq_client);
		synths[card->number] = NULL;
		kfree(client);
	}
	mutex_unlock(&register_mutex);
	return 0;
}
예제 #5
0
/* unregister our internal client */
void __exit snd_seq_system_client_done(void)
{
	int oldsysclient = sysclient;

	if (oldsysclient >= 0) {
		sysclient = -1;
		announce_port = -1;
		snd_seq_delete_kernel_client(oldsysclient);
	}
}
예제 #6
0
static int snd_opl4_seq_new_device(struct snd_seq_device *dev)
{
    struct snd_opl4 *opl4;
    int client;
    struct snd_seq_port_callback pcallbacks;

    opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
    if (!opl4)
        return -EINVAL;

    if (snd_yrw801_detect(opl4) < 0)
        return -ENODEV;

    opl4->chset = snd_midi_channel_alloc_set(16);
    if (!opl4->chset)
        return -ENOMEM;
    opl4->chset->private_data = opl4;

    /* allocate new client */
    client = snd_seq_create_kernel_client(opl4->card, opl4->seq_dev_num,
                                          "OPL4 Wavetable");
    if (client < 0) {
        snd_midi_channel_free_set(opl4->chset);
        return client;
    }
    opl4->seq_client = client;
    opl4->chset->client = client;

    /* create new port */
    memset(&pcallbacks, 0, sizeof(pcallbacks));
    pcallbacks.owner = THIS_MODULE;
    pcallbacks.use = snd_opl4_seq_use;
    pcallbacks.unuse = snd_opl4_seq_unuse;
    pcallbacks.event_input = snd_opl4_seq_event_input;
    pcallbacks.private_free = snd_opl4_seq_free_port;
    pcallbacks.private_data = opl4;

    opl4->chset->port = snd_seq_event_port_attach(client, &pcallbacks,
                        SNDRV_SEQ_PORT_CAP_WRITE |
                        SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
                        SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
                        SNDRV_SEQ_PORT_TYPE_MIDI_GM |
                        SNDRV_SEQ_PORT_TYPE_HARDWARE |
                        SNDRV_SEQ_PORT_TYPE_SYNTHESIZER,
                        16, 24,
                        "OPL4 Wavetable Port");
    if (opl4->chset->port < 0) {
        int err = opl4->chset->port;
        snd_midi_channel_free_set(opl4->chset);
        snd_seq_delete_kernel_client(client);
        opl4->seq_client = -1;
        return err;
    }
    return 0;
}
예제 #7
0
/*
 * Detach from the ports that were set up for this synthesizer and
 * destroy the kernel client.
 */
void
snd_emux_detach_seq(struct snd_emux *emu)
{
	if (emu->voices)
		snd_emux_terminate_all(emu);

	mutex_lock(&emu->register_mutex);
	if (emu->client >= 0) {
		snd_seq_delete_kernel_client(emu->client);
		emu->client = -1;
	}
	mutex_unlock(&emu->register_mutex);
}
예제 #8
0
/*
 * Detach from the ports that were set up for this synthesizer and
 * destroy the kernel client.
 */
void
snd_emux_detach_seq(snd_emux_t *emu)
{
	if (emu->voices)
		snd_emux_terminate_all(emu);
		
	down(&emu->register_mutex);
	if (emu->client >= 0) {
		snd_seq_delete_kernel_client(emu->client);
		emu->client = -1;
	}
	up(&emu->register_mutex);
}
예제 #9
0
static int snd_opl4_seq_delete_device(struct snd_seq_device *dev)
{
    struct snd_opl4 *opl4;

    opl4 = *(struct snd_opl4 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
    if (!opl4)
        return -EINVAL;

    if (opl4->seq_client >= 0) {
        snd_seq_delete_kernel_client(opl4->seq_client);
        opl4->seq_client = -1;
    }
    return 0;
}
예제 #10
0
/*
 * register client and create ports
 */
static int __init
register_client(void)
{
	struct snd_seq_dummy_port *rec1, *rec2;
	int i;

	if (ports < 1) {
		snd_printk(KERN_ERR "invalid number of ports %d\n", ports);
		return -EINVAL;
	}

	/* create client */
	my_client = snd_seq_create_kernel_client(NULL, SNDRV_SEQ_CLIENT_DUMMY,
						 "Midi Through");
	if (my_client < 0)
		return my_client;

	/* create ports */
	for (i = 0; i < ports; i++) {
		rec1 = create_port(i, 0);
		if (rec1 == NULL) {
			snd_seq_delete_kernel_client(my_client);
			return -ENOMEM;
		}
		if (duplex) {
			rec2 = create_port(i, 1);
			if (rec2 == NULL) {
				snd_seq_delete_kernel_client(my_client);
				return -ENOMEM;
			}
			rec1->connect = rec2->port;
			rec2->connect = rec1->port;
		}
	}

	return 0;
}
예제 #11
0
static int snd_gus_synth_delete_device(snd_seq_device_t *dev)
{
    snd_gus_card_t *gus;

    gus = *(snd_gus_card_t**)SNDRV_SEQ_DEVICE_ARGPTR(dev);
    if (gus == NULL)
        return -EINVAL;

    if (gus->gf1.seq_client >= 0) {
        snd_seq_delete_kernel_client(gus->gf1.seq_client);
        gus->gf1.seq_client = -1;
    }
    if (gus->gf1.ilist)
        snd_seq_instr_list_free(&gus->gf1.ilist);
    return 0;
}
예제 #12
0
/*
 * delete client if exists
 */
void ALSADeleteClient(struct ALSADriver *driver)
{
	if (driver == NULL) {
		return;
	}
	if (driver->client != 0) {
		snd_seq_delete_kernel_client(driver->client);
	}
	if (driver->card != NULL) {
		snd_card_free(driver->card);
	}
	if (driver->priv != NULL) {
		kfree(driver->priv);
	}
	kfree(driver);
	pr_debug("freed alsa port\n");
}
예제 #13
0
파일: opl3_seq.c 프로젝트: 274914765/C
static int snd_opl3_seq_delete_device(struct snd_seq_device *dev)
{
    struct snd_opl3 *opl3;

    opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
    if (opl3 == NULL)
        return -EINVAL;

#ifdef CONFIG_SND_SEQUENCER_OSS
    snd_opl3_free_seq_oss(opl3);
#endif
    if (opl3->seq_client >= 0) {
        snd_seq_delete_kernel_client(opl3->seq_client);
        opl3->seq_client = -1;
    }
    return 0;
}
예제 #14
0
파일: opl3_seq.c 프로젝트: mdamt/linux
static int snd_opl3_seq_probe(struct device *_dev)
{
	struct snd_seq_device *dev = to_seq_dev(_dev);
	struct snd_opl3 *opl3;
	int client, err;
	char name[32];
	int opl_ver;

	opl3 = *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
	if (opl3 == NULL)
		return -EINVAL;

	spin_lock_init(&opl3->voice_lock);

	opl3->seq_client = -1;

	/* allocate new client */
	opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8;
	sprintf(name, "OPL%i FM synth", opl_ver);
	client = opl3->seq_client =
		snd_seq_create_kernel_client(opl3->card, opl3->seq_dev_num,
					     name);
	if (client < 0)
		return client;

	if ((err = snd_opl3_synth_create_port(opl3)) < 0) {
		snd_seq_delete_kernel_client(client);
		opl3->seq_client = -1;
		return err;
	}

	/* setup system timer */
	setup_timer(&opl3->tlist, snd_opl3_timer_func, (unsigned long) opl3);
	spin_lock_init(&opl3->sys_timer_lock);
	opl3->sys_timer_status = 0;

#if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
	snd_opl3_init_seq_oss(opl3, name);
#endif
	return 0;
}
예제 #15
0
/* register new midi synth port */
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, p, ports;
	snd_seq_client_callback_t callbacks;
	snd_seq_port_callback_t pcallbacks;
	snd_seq_client_info_t inf;
	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.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)
		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 = snd_kcalloc(sizeof(seq_midisynth_client_t), GFP_KERNEL);
		if (client == NULL) {
			up(&register_mutex);
			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);
			return -ENOMEM;
		}
		/* set our client name */
		memset(&inf,0,sizeof(snd_seq_client_info_t));
		inf.client = client->seq_client;
		inf.type = KERNEL_CLIENT;
		sprintf(inf.name, "External MIDI %i", card->number);
		snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &inf);
	}

	msynth = snd_kcalloc(sizeof(seq_midisynth_t) * ports, GFP_KERNEL);
	if (msynth == 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 (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);
	}
	up(&register_mutex);
	return -ENOMEM;
}
예제 #16
0
/* register new midi synth port */
static int
snd_seq_midisynth_register_port(struct snd_seq_device *dev)
{
	struct seq_midisynth_client *client;
	struct seq_midisynth *msynth, *ms;
	struct snd_seq_port_info *port;
	struct snd_rawmidi_info *info;
	struct snd_rawmidi *rmidi = dev->private_data;
	int newclient = 0;
	unsigned int p, ports;
	struct snd_seq_port_callback pcallbacks;
	struct snd_card *card = dev->card;
	int device = dev->device;
	unsigned int input_count = 0, output_count = 0;

	if (snd_BUG_ON(!card || 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;

	mutex_lock(&register_mutex);
	client = synths[card->number];
	if (client == NULL) {
		newclient = 1;
		client = kzalloc(sizeof(*client), GFP_KERNEL);
		if (client == NULL) {
			mutex_unlock(&register_mutex);
			kfree(info);
			return -ENOMEM;
		}
		client->seq_client =
			snd_seq_create_kernel_client(
				card, 0, "%s", card->shortname[0] ?
				(const char *)card->shortname : "External MIDI");
		if (client->seq_client < 0) {
			kfree(client);
			mutex_unlock(&register_mutex);
			kfree(info);
			return -ENOMEM;
		}
	}

	msynth = kcalloc(ports, sizeof(struct seq_midisynth), 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
			| SNDRV_SEQ_PORT_TYPE_HARDWARE
			| SNDRV_SEQ_PORT_TYPE_PORT;
		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 (rmidi->ops && rmidi->ops->get_port_info)
			rmidi->ops->get_port_info(rmidi, p, port);
		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;
	mutex_unlock(&register_mutex);
	kfree(info);
	kfree(port);
	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);
	mutex_unlock(&register_mutex);
	return -ENOMEM;
}
예제 #17
0
/*
 * delete client if exists
 */
static void __exit
delete_client(void)
{
	if (my_client >= 0)
		snd_seq_delete_kernel_client(my_client);
}
예제 #18
0
void exit_midi(void) {
    snd_seq_delete_kernel_client(client);
    snd_card_free(card);
}
예제 #19
0
/*
 * register client and create port
 */
struct ALSADriver *ALSARegisterClient(void *drv)
{

	struct ALSADriver *driver;

	int ret, err;

	printk("registering alsa client\n");

	driver = kmalloc(sizeof(struct ALSADriver), GFP_KERNEL);

	driver->priv = kmalloc(sizeof(struct privateData), GFP_KERNEL);

	driver->priv->list.message = &(driver->priv->msg);
	driver->priv->list.next = NULL;
	driver->priv->drv = drv;

	err = snd_card_create(-1, NULL, THIS_MODULE, sizeof(struct snd_card),
			      &(driver->card));
	if (err < 0) {
		pr_err("alsa error creating card: %d\n", err);
		goto fail_card;
	}

	/* create client */
	driver->client =
	    snd_seq_create_kernel_client(driver->card, 0, "AppleMidi");
	if (driver->client < 0) {
		pr_err("failed to register alsa client : %d\n", driver->client);
		goto fail_client;
	}

	/* create port */
	pr_debug("register alsa port\n");
	ret = _create_port(driver->client, 0, 0, driver->priv);
	if (ret < 0) {
		goto fail_port;
	}

	pr_debug("registering snd card\n");
	err = snd_card_register(driver->card);
	if (err < 0) {
		pr_err("failed to register card:err:%d\n", err);
		goto fail_port;
	}

	pr_debug("registered alsa client\n");

	return driver;

fail_port:
	snd_seq_delete_kernel_client(driver->client);

fail_client:
	snd_card_free(driver->card);

fail_card:
	kfree(driver->priv);
	kfree(driver);

	return (NULL);
}
예제 #20
0
static int snd_gus_synth_new_device(snd_seq_device_t *dev)
{
    snd_gus_card_t *gus;
    int client, i;
    snd_seq_client_callback_t callbacks;
    snd_seq_client_info_t *cinfo;
    snd_seq_port_subscribe_t sub;
    snd_iwffff_ops_t *iwops;
    snd_gf1_ops_t *gf1ops;
    snd_simple_ops_t *simpleops;

    gus = *(snd_gus_card_t**)SNDRV_SEQ_DEVICE_ARGPTR(dev);
    if (gus == NULL)
        return -EINVAL;

    init_MUTEX(&gus->register_mutex);
    gus->gf1.seq_client = -1;

    cinfo = kmalloc(sizeof(*cinfo), GFP_KERNEL);
    if (! cinfo)
        return -ENOMEM;

    /* allocate new client */
    memset(&callbacks, 0, sizeof(callbacks));
    callbacks.private_data = gus;
    callbacks.allow_output = callbacks.allow_input = 1;
    client = gus->gf1.seq_client =
                 snd_seq_create_kernel_client(gus->card, 1, &callbacks);
    if (client < 0) {
        kfree(cinfo);
        return client;
    }

    /* change name of client */
    memset(cinfo, 0, sizeof(*cinfo));
    cinfo->client = client;
    cinfo->type = KERNEL_CLIENT;
    sprintf(cinfo->name, gus->interwave ? "AMD InterWave" : "GF1");
    snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, cinfo);
    kfree(cinfo);

    for (i = 0; i < 4; i++)
        snd_gus_synth_create_port(gus, i);

    gus->gf1.ilist = snd_seq_instr_list_new();
    if (gus->gf1.ilist == NULL) {
        snd_seq_delete_kernel_client(client);
        gus->gf1.seq_client = -1;
        return -ENOMEM;
    }
    gus->gf1.ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT;

    simpleops = &gus->gf1.simple_ops;
    snd_seq_simple_init(simpleops, gus, NULL);
    simpleops->put_sample = snd_gus_simple_put_sample;
    simpleops->get_sample = snd_gus_simple_get_sample;
    simpleops->remove_sample = snd_gus_simple_remove_sample;
    simpleops->notify = snd_gus_synth_instr_notify;

    gf1ops = &gus->gf1.gf1_ops;
    snd_seq_gf1_init(gf1ops, gus, &simpleops->kops);
    gf1ops->put_sample = snd_gus_gf1_put_sample;
    gf1ops->get_sample = snd_gus_gf1_get_sample;
    gf1ops->remove_sample = snd_gus_gf1_remove_sample;
    gf1ops->notify = snd_gus_synth_instr_notify;

    iwops = &gus->gf1.iwffff_ops;
    snd_seq_iwffff_init(iwops, gus, &gf1ops->kops);
    iwops->put_sample = snd_gus_iwffff_put_sample;
    iwops->get_sample = snd_gus_iwffff_get_sample;
    iwops->remove_sample = snd_gus_iwffff_remove_sample;
    iwops->notify = snd_gus_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;
}