sound/core/seq/seq_prioq.c

Source file repositories/reference/linux-study-clean/sound/core/seq/seq_prioq.c

File Facts

System
Linux kernel
Corpus path
sound/core/seq/seq_prioq.c
Extension
.c
Size
9702 bytes
Lines
403
Domain
Driver Families
Bucket
sound/core
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct prioq_match_arg {
	int client;
	int timestamp;
};

static inline bool prioq_match(struct snd_seq_event_cell *cell, void *arg)
{
	struct prioq_match_arg *v = arg;

	if (cell->event.source.client == v->client ||
	    cell->event.dest.client == v->client)
		return true;
	if (!v->timestamp)
		return false;
	switch (cell->event.flags & SNDRV_SEQ_TIME_STAMP_MASK) {
	case SNDRV_SEQ_TIME_STAMP_TICK:
		if (cell->event.time.tick)
			return true;
		break;
	case SNDRV_SEQ_TIME_STAMP_REAL:
		if (cell->event.time.time.tv_sec ||
		    cell->event.time.time.tv_nsec)
			return true;
		break;
	}
	return false;
}

/* remove cells for left client */
void snd_seq_prioq_leave(struct snd_seq_prioq *f, int client, int timestamp)
{
	struct prioq_match_arg arg = { client, timestamp };

	return prioq_remove_cells(f, prioq_match, &arg);
}

struct prioq_remove_match_arg {
	int client;
	struct snd_seq_remove_events *info;
};

static bool prioq_remove_match(struct snd_seq_event_cell *cell, void *arg)
{
	struct prioq_remove_match_arg *v = arg;
	struct snd_seq_event *ev = &cell->event;
	struct snd_seq_remove_events *info = v->info;
	int res;

	if (ev->source.client != v->client)
		return false;

	if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST) {
		if (ev->dest.client != info->dest.client ||
				ev->dest.port != info->dest.port)
			return false;
	}
	if (info->remove_mode & SNDRV_SEQ_REMOVE_DEST_CHANNEL) {
		if (! snd_seq_ev_is_channel_type(ev))
			return false;
		/* data.note.channel and data.control.channel are identical */
		if (ev->data.note.channel != info->channel)
			return false;
	}
	if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_AFTER) {
		if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
			res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick);
		else
			res = snd_seq_compare_real_time(&ev->time.time, &info->time.time);
		if (!res)
			return false;
	}
	if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_BEFORE) {
		if (info->remove_mode & SNDRV_SEQ_REMOVE_TIME_TICK)
			res = snd_seq_compare_tick_time(&ev->time.tick, &info->time.tick);
		else
			res = snd_seq_compare_real_time(&ev->time.time, &info->time.time);
		if (res)
			return false;
	}
	if (info->remove_mode & SNDRV_SEQ_REMOVE_EVENT_TYPE) {
		if (ev->type != info->type)
			return false;
	}
	if (info->remove_mode & SNDRV_SEQ_REMOVE_IGNORE_OFF) {
		/* Do not remove off events */
		switch (ev->type) {
		case SNDRV_SEQ_EVENT_NOTEOFF:
		/* case SNDRV_SEQ_EVENT_SAMPLE_STOP: */
			return false;
		default:

Annotation

Implementation Notes