Beispiel #1
0
static int
insert_queue(struct seq_oss_devinfo *dp, union evrec *rec, struct file *opt)
{
	int rc = 0;
	struct snd_seq_event event;

	/* if this is a timing event, process the current time */
	if (snd_seq_oss_process_timer_event(dp->timer, rec))
		return 0; /* no need to insert queue */

	/* parse this event */
	memset(&event, 0, sizeof(event));
	/* set dummy -- to be sure */
	event.type = SNDRV_SEQ_EVENT_NOTEOFF;
	snd_seq_oss_fill_addr(dp, &event, dp->addr.port, dp->addr.client);

	if (snd_seq_oss_process_event(dp, rec, &event))
		return 0; /* invalid event - no need to insert queue */

	event.time.tick = snd_seq_oss_timer_cur_tick(dp->timer);
	if (dp->timer->realtime || !dp->timer->running) {
		snd_seq_oss_dispatch(dp, &event, 0, 0);
	} else {
		if (is_nonblock_mode(dp->file_mode))
			rc = snd_seq_kernel_client_enqueue(dp->cseq, &event, 0, 0);
		else
			rc = snd_seq_kernel_client_enqueue_blocking(dp->cseq, &event, opt, 0, 0);
	}
	return rc;
}
Beispiel #2
0
/*
 * fill the event source/destination addresses
 */
int
snd_seq_oss_synth_addr(seq_oss_devinfo_t *dp, int dev, snd_seq_event_t *ev)
{
	if (! snd_seq_oss_synth_is_valid(dp, dev))
		return -EINVAL;
	snd_seq_oss_fill_addr(dp, ev, dp->synths[dev].arg.addr.client,
			      dp->synths[dev].arg.addr.port);
	return 0;
}
/*
 * create an echo event
 */
static int
set_echo_event(seq_oss_devinfo_t *dp, evrec_t *rec, snd_seq_event_t *ev)
{
	ev->type = SNDRV_SEQ_EVENT_ECHO;
	/* echo back to itself */
	snd_seq_oss_fill_addr(dp, ev, dp->addr.client, dp->addr.port);
	memcpy(&ev->data, rec, LONG_EVENT_SIZE);
	return 0;
}
/*
 * wait until the write buffer has enough room
 */
int
snd_seq_oss_writeq_sync(seq_oss_writeq_t *q)
{
	seq_oss_devinfo_t *dp = q->dp;
	abstime_t time;
	unsigned long flags;

	time = snd_seq_oss_timer_cur_tick(dp->timer);
	if (q->sync_time >= time)
		return 0; /* already finished */

	if (! q->sync_event_put) {
		snd_seq_event_t ev;
		evrec_t *rec;

		/* put echoback event */
		memset(&ev, 0, sizeof(ev));
		ev.flags = 0;
		ev.type = SNDRV_SEQ_EVENT_ECHO;
		ev.time.tick = time;
		/* echo back to itself */
		snd_seq_oss_fill_addr(dp, &ev, dp->addr.client, dp->addr.port);
		rec = (evrec_t*)&ev.data;
		rec->t.code = SEQ_SYNCTIMER;
		rec->t.time = time;
		q->sync_event_put = 1;
		snd_seq_kernel_client_enqueue_blocking(dp->cseq, &ev, NULL, 0, 0);
	}

	spin_lock_irqsave(&q->sync_lock, flags);
	if (! q->sync_event_put) { /* echoback event has been received */
		spin_unlock_irqrestore(&q->sync_lock, flags);
		return 0;
	}
		
	/* wait for echo event */
	spin_unlock(&q->sync_lock);
	interruptible_sleep_on_timeout(&q->sync_sleep, HZ);
	spin_lock(&q->sync_lock);
	if (signal_pending(current)) {
		/* interrupted - return 0 to finish sync */
		q->sync_event_put = 0;
		spin_unlock_irqrestore(&q->sync_lock, flags);
		return 0;
	}
	spin_unlock_irqrestore(&q->sync_lock, flags);
	if (q->sync_time >= time)
		return 0;
	else
		return 1;
}
Beispiel #5
0
/*
 * reset synth device:
 * call reset callback.  if no callback is defined, send a heartbeat
 * event to the corresponding port.
 */
void
snd_seq_oss_synth_reset(seq_oss_devinfo_t *dp, int dev)
{
	seq_oss_synth_t *rec;
	seq_oss_synthinfo_t *info;

	snd_assert(dev >= 0 && dev < dp->max_synthdev, return);
	info = &dp->synths[dev];
	if (! info->opened)
		return;
	if (info->sysex)
		info->sysex->len = 0; /* reset sysex */
	reset_channels(info);
	if (info->is_midi) {
		if (midi_synth_dev.opened <= 0)
			return;
		snd_seq_oss_midi_reset(dp, info->midi_mapped);
		/* reopen the device */
		snd_seq_oss_midi_close(dp, dev);
		if (snd_seq_oss_midi_open(dp, info->midi_mapped,
					  dp->file_mode) < 0) {
			midi_synth_dev.opened--;
			info->opened = 0;
			if (info->sysex) {
				kfree(info->sysex);
				info->sysex = NULL;
			}
			if (info->ch) {
				kfree(info->ch);
				info->ch = NULL;
			}
		}
		return;
	}

	rec = get_sdev(dev);
	if (rec == NULL)
		return;
	if (rec->oper.reset) {
		rec->oper.reset(&info->arg);
	} else {
		snd_seq_event_t ev;
		memset(&ev, 0, sizeof(ev));
		snd_seq_oss_fill_addr(dp, &ev, info->arg.addr.client,
				      info->arg.addr.port);
		ev.type = SNDRV_SEQ_EVENT_RESET;
		snd_seq_oss_dispatch(dp, &ev, 0, 0);
	}
	snd_use_lock_free(&rec->use_lock);
}
Beispiel #6
0
static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg)
{
	unsigned char ev[8];
	struct snd_seq_event tmpev;

	if (copy_from_user(ev, arg, 8))
		return -EFAULT;
	memset(&tmpev, 0, sizeof(tmpev));
	snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client);
	tmpev.time.tick = 0;
	if (! snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev)) {
		snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
	}
	return 0;
}
Beispiel #7
0
/*
 * dump midi data
 * return 0 : enqueued
 *        non-zero : invalid - ignored
 */
int
snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev)
{
	struct seq_oss_midi *mdev;

	if ((mdev = get_mididev(dp, dev)) == NULL)
		return -ENODEV;
	if (snd_midi_event_encode_byte(mdev->coder, c, ev) > 0) {
		snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port);
		snd_use_lock_free(&mdev->use_lock);
		return 0;
	}
	snd_use_lock_free(&mdev->use_lock);
	return -EINVAL;
}
Beispiel #8
0
/*
 * wait until the write buffer has enough room
 */
int
snd_seq_oss_writeq_sync(struct seq_oss_writeq *q)
{
	struct seq_oss_devinfo *dp = q->dp;
	abstime_t time;

	time = snd_seq_oss_timer_cur_tick(dp->timer);
	if (q->sync_time >= time)
		return 0; /* already finished */

	if (! q->sync_event_put) {
		struct snd_seq_event ev;
		union evrec *rec;

		/* put echoback event */
		memset(&ev, 0, sizeof(ev));
		ev.flags = 0;
		ev.type = SNDRV_SEQ_EVENT_ECHO;
		ev.time.tick = time;
		/* echo back to itself */
		snd_seq_oss_fill_addr(dp, &ev, dp->addr.client, dp->addr.port);
		rec = (union evrec *)&ev.data;
		rec->t.code = SEQ_SYNCTIMER;
		rec->t.time = time;
		q->sync_event_put = 1;
		snd_seq_kernel_client_enqueue_blocking(dp->cseq, &ev, NULL, 0, 0);
	}

	wait_event_interruptible_timeout(q->sync_sleep, ! q->sync_event_put, HZ);
	if (signal_pending(current))
		/* interrupted - return 0 to finish sync */
		q->sync_event_put = 0;
	if (! q->sync_event_put || q->sync_time >= time)
		return 0;
	return 1;
}