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

📄 seq_queue.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
/* exported - only checking permission */int snd_seq_queue_check_access(int queueid, int client){	queue_t *q = queueptr(queueid);	int access_ok;	unsigned long flags;	if (! q)		return 0;	spin_lock_irqsave(&q->owner_lock, flags);	access_ok = check_access(q, client);	spin_unlock_irqrestore(&q->owner_lock, flags);	queuefree(q);	return access_ok;}/*----------------------------------------------------------------*//* * change queue's owner and permission */int snd_seq_queue_set_owner(int queueid, int client, int locked){	queue_t *q = queueptr(queueid);	if (q == NULL)		return -EINVAL;	if (! queue_access_lock(q, client)) {		queuefree(q);		return -EPERM;	}	q->locked = locked ? 1 : 0;	q->owner = client;	queue_access_unlock(q);	queuefree(q);	return 0;}/*----------------------------------------------------------------*//* open timer - * q->use mutex should be down before calling this function to avoid * confliction with snd_seq_queue_use() */int snd_seq_queue_timer_open(int queueid){	int result = 0;	queue_t *queue;	seq_timer_t *tmr;	queue = queueptr(queueid);	if (queue == NULL)		return -EINVAL;	tmr = queue->timer;	if ((result = snd_seq_timer_open(queue)) < 0) {		snd_seq_timer_defaults(tmr);		result = snd_seq_timer_open(queue);	}	queuefree(queue);	return result;}/* close timer - * q->use mutex should be down before calling this function */int snd_seq_queue_timer_close(int queueid){	queue_t *queue;	seq_timer_t *tmr;	int result = 0;	queue = queueptr(queueid);	if (queue == NULL)		return -EINVAL;	tmr = queue->timer;	snd_seq_timer_close(queue);	queuefree(queue);	return result;}/* change queue tempo and ppq */int snd_seq_queue_timer_set_tempo(int queueid, int client, snd_seq_queue_tempo_t *info){	queue_t *q = queueptr(queueid);	int result;	if (q == NULL)		return -EINVAL;	if (! queue_access_lock(q, client)) {		queuefree(q);		return -EPERM;	}	result = snd_seq_timer_set_tempo(q->timer, info->tempo);	if (result >= 0)		result = snd_seq_timer_set_ppq(q->timer, info->ppq);	if (result >= 0 && info->skew_base > 0)		result = snd_seq_timer_set_skew(q->timer, info->skew_value, info->skew_base);	queue_access_unlock(q);	queuefree(q);	return result;}/* use or unuse this queue - * if it is the first client, starts the timer. * if it is not longer used by any clients, stop the timer. */int snd_seq_queue_use(int queueid, int client, int use){	queue_t *queue;	queue = queueptr(queueid);	if (queue == NULL)		return -EINVAL;	down(&queue->timer_mutex);	if (use) {		if (!test_and_set_bit(client, queue->clients_bitmap))			queue->clients++;	} else {		if (test_and_clear_bit(client, queue->clients_bitmap))			queue->clients--;	}	if (queue->clients) {		if (use && queue->clients == 1)			snd_seq_timer_defaults(queue->timer);		snd_seq_timer_open(queue);	} else {		snd_seq_timer_close(queue);	}	up(&queue->timer_mutex);	queuefree(queue);	return 0;}/* * check if queue is used by the client * return negative value if the queue is invalid. * return 0 if not used, 1 if used. */int snd_seq_queue_is_used(int queueid, int client){	queue_t *q;	int result;	q = queueptr(queueid);	if (q == NULL)		return -EINVAL; /* invalid queue */	result = test_bit(client, q->clients_bitmap) ? 1 : 0;	queuefree(q);	return result;}/*----------------------------------------------------------------*//* notification that client has left the system - * stop the timer on all queues owned by this client */void snd_seq_queue_client_termination(int client){	unsigned long flags;	int i;	queue_t *q;	for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {		if ((q = queueptr(i)) == NULL)			continue;		spin_lock_irqsave(&q->owner_lock, flags);		if (q->owner == client)			q->klocked = 1;		spin_unlock_irqrestore(&q->owner_lock, flags);		if (q->owner == client) {			if (q->timer->running)				snd_seq_timer_stop(q->timer);			snd_seq_timer_reset(q->timer);		}		queuefree(q);	}}/* final stage notification - * remove cells for no longer exist client (for non-owned queue) * or delete this queue (for owned queue) */void snd_seq_queue_client_leave(int client){	int i;	queue_t *q;	/* delete own queues from queue list */	for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {		if ((q = queue_list_remove(i, client)) != NULL)			queue_delete(q);	}	/* remove cells from existing queues -	 * they are not owned by this client	 */	for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {		if ((q = queueptr(i)) == NULL)			continue;		if (test_bit(client, q->clients_bitmap)) {			snd_seq_prioq_leave(q->tickq, client, 0);			snd_seq_prioq_leave(q->timeq, client, 0);			snd_seq_queue_use(q->queue, client, 0);		}		queuefree(q);	}}/*----------------------------------------------------------------*//* remove cells from all queues */void snd_seq_queue_client_leave_cells(int client){	int i;	queue_t *q;	for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {		if ((q = queueptr(i)) == NULL)			continue;		snd_seq_prioq_leave(q->tickq, client, 0);		snd_seq_prioq_leave(q->timeq, client, 0);		queuefree(q);	}}/* remove cells based on flush criteria */void snd_seq_queue_remove_cells(int client, snd_seq_remove_events_t *info){	int i;	queue_t *q;	for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {		if ((q = queueptr(i)) == NULL)			continue;		if (test_bit(client, q->clients_bitmap) &&		    (! (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) ||		     q->queue == info->queue)) {			snd_seq_prioq_remove_events(q->tickq, client, info);			snd_seq_prioq_remove_events(q->timeq, client, info);		}		queuefree(q);	}}/*----------------------------------------------------------------*//* * send events to all subscribed ports */static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop){	snd_seq_event_t sev;	sev = *ev;		sev.flags = SNDRV_SEQ_TIME_STAMP_TICK|SNDRV_SEQ_TIME_MODE_ABS;	sev.time.tick = q->timer->tick.cur_tick;	sev.queue = q->queue;	sev.data.queue.queue = q->queue;	/* broadcast events from Timer port */	sev.source.client = SNDRV_SEQ_CLIENT_SYSTEM;	sev.source.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;	sev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;	snd_seq_kernel_client_dispatch(SNDRV_SEQ_CLIENT_SYSTEM, &sev, atomic, hop);}/* * process a received queue-control event. * this function is exported for seq_sync.c. */static void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev,					int atomic, int hop){	switch (ev->type) {	case SNDRV_SEQ_EVENT_START:		snd_seq_prioq_leave(q->tickq, ev->source.client, 1);		snd_seq_prioq_leave(q->timeq, ev->source.client, 1);		if (! snd_seq_timer_start(q->timer))			queue_broadcast_event(q, ev, atomic, hop);		break;	case SNDRV_SEQ_EVENT_CONTINUE:		if (! snd_seq_timer_continue(q->timer))			queue_broadcast_event(q, ev, atomic, hop);		break;	case SNDRV_SEQ_EVENT_STOP:		snd_seq_timer_stop(q->timer);		queue_broadcast_event(q, ev, atomic, hop);		break;	case SNDRV_SEQ_EVENT_TEMPO:		snd_seq_timer_set_tempo(q->timer, ev->data.queue.param.value);		queue_broadcast_event(q, ev, atomic, hop);		break;	case SNDRV_SEQ_EVENT_SETPOS_TICK:		if (snd_seq_timer_set_position_tick(q->timer, ev->data.queue.param.time.tick) == 0) {			queue_broadcast_event(q, ev, atomic, hop);		}		break;	case SNDRV_SEQ_EVENT_SETPOS_TIME:		if (snd_seq_timer_set_position_time(q->timer, ev->data.queue.param.time.time) == 0) {			queue_broadcast_event(q, ev, atomic, hop);		}		break;	case SNDRV_SEQ_EVENT_QUEUE_SKEW:		if (snd_seq_timer_set_skew(q->timer,					   ev->data.queue.param.skew.value,					   ev->data.queue.param.skew.base) == 0) {			queue_broadcast_event(q, ev, atomic, hop);		}		break;	}}/* * Queue control via timer control port: * this function is exported as a callback of timer port. */int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop){	queue_t *q;	snd_assert(ev != NULL, return -EINVAL);	q = queueptr(ev->data.queue.queue);	if (q == NULL)		return -EINVAL;	if (! queue_access_lock(q, ev->source.client)) {		queuefree(q);		return -EPERM;	}	snd_seq_queue_process_event(q, ev, atomic, hop);	queue_access_unlock(q);	queuefree(q);	return 0;}/*----------------------------------------------------------------*//* exported to seq_info.c */void snd_seq_info_queues_read(snd_info_entry_t *entry, 			      snd_info_buffer_t * buffer){	int i, bpm;	queue_t *q;	seq_timer_t *tmr;	for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {		if ((q = queueptr(i)) == NULL)			continue;		tmr = q->timer;		if (tmr->tempo)			bpm = 60000000 / tmr->tempo;		else			bpm = 0;		snd_iprintf(buffer, "queue %d: [%s]\n", q->queue, q->name);		snd_iprintf(buffer, "owned by client    : %d\n", q->owner);		snd_iprintf(buffer, "lock status        : %s\n", q->locked ? "Locked" : "Free");		snd_iprintf(buffer, "queued time events : %d\n", snd_seq_prioq_avail(q->timeq));		snd_iprintf(buffer, "queued tick events : %d\n", snd_seq_prioq_avail(q->tickq));		snd_iprintf(buffer, "timer state        : %s\n", tmr->running ? "Running" : "Stopped");		snd_iprintf(buffer, "timer PPQ          : %d\n", tmr->ppq);		snd_iprintf(buffer, "current tempo      : %d\n", tmr->tempo);		snd_iprintf(buffer, "current BPM        : %d\n", bpm);		snd_iprintf(buffer, "current time       : %d.%09d s\n", tmr->cur_time.tv_sec, tmr->cur_time.tv_nsec);		snd_iprintf(buffer, "current tick       : %d\n", tmr->tick.cur_tick);		snd_iprintf(buffer, "\n");		queuefree(q);	}}

⌨️ 快捷键说明

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